diff --git a/.circleci/config.yml b/.circleci/config.yml index 63eae308c49f..30eec16e5ae0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -38,28 +38,16 @@ commands: steps: - run: command: | + export DEBIAN_FRONTEND=noninteractive sudo apt-get update && sudo apt-get install -y libssh-dev install-deps: steps: - run: command: | - 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 --disable-pip-version-check --no-input --no-cache-dir install --progress-bar off --prefer-binary -r tests/requirements.txt - - install-wolfssl: - steps: - - run: - command: | - # renovate: datasource=github-tags depName=wolfSSL/wolfssl versioning=semver extractVersion=^v?(?.+)-stable$ registryUrl=https://github.com - WOLFSSL_VERSION=5.8.0 - echo "Installing wolfSSL $WOLFSSL_VERSION" - curl --disable --fail --silent --show-error --connect-timeout 15 --max-time 120 --retry 6 --retry-connrefused \ - --location "https://github.com/wolfSSL/wolfssl/archive/v$WOLFSSL_VERSION-stable.tar.gz" | tar -xz - cd wolfssl-$WOLFSSL_VERSION-stable - ./autogen.sh - ./configure --disable-dependency-tracking --enable-tls13 --enable-all --enable-harden --prefix=$HOME/wssl - make install + sudo apt-get update && sudo apt-get install -y libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev python3-pip + python3 -m venv ~/venv + ~/venv/bin/pip --disable-pip-version-check --no-input --no-cache-dir install --progress-bar off --prefer-binary -r tests/requirements.txt configure: steps: @@ -109,16 +97,24 @@ commands: build: steps: - run: make -j3 V=1 + - run: src/curl --disable --version - run: make -j3 V=1 examples test: steps: - - run: make -j3 V=1 test-ci TFLAGS='-j14' + - run: + command: | + source ~/venv/bin/activate + # Revert a CircleCI-specific local setting that makes test 1459 + # return 67 (CURLE_LOGIN_DENIED) instead of the + # expected 60 (CURLE_PEER_FAILED_VERIFICATION). + echo 'StrictHostKeyChecking yes' >> ~/.ssh/config + make -j3 V=1 test-ci TFLAGS='-j14' executors: ubuntu: machine: - image: ubuntu-2004:2024.01.1 + image: ubuntu-2204:2025.09.1 jobs: basic: @@ -161,7 +157,7 @@ jobs: arm: machine: - image: ubuntu-2004:2024.01.1 + image: ubuntu-2204:2025.09.1 resource_class: arm.medium steps: - checkout @@ -172,7 +168,7 @@ jobs: arm-cares: machine: - image: ubuntu-2004:2024.01.1 + image: ubuntu-2204:2025.09.1 resource_class: arm.medium steps: - checkout diff --git a/.github/dependabot.yml b/.github/dependabot.yml index bd5661bea41a..c68d6301ef4f 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -2,20 +2,37 @@ # # SPDX-License-Identifier: curl +# https://docs.github.com/code-security/dependabot/working-with-dependabot/dependabot-options-reference + version: 2 updates: - package-ecosystem: 'github-actions' directory: '/' schedule: interval: 'monthly' + cooldown: + default-days: 7 + groups: + gha-dependencies: + patterns: + - '*' commit-message: prefix: 'GHA:' - package-ecosystem: 'pip' directories: - - '/.github/scripts' - - '/tests' + - '.github/scripts' + - 'tests' schedule: interval: 'monthly' + cooldown: + default-days: 7 + semver-major-days: 15 + semver-minor-days: 7 + semver-patch-days: 3 + groups: + pip-dependencies: + patterns: + - '*' commit-message: prefix: 'GHA:' diff --git a/.github/labeler.yml b/.github/labeler.yml index 982055f16a3b..a3ca5d38be8c 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -11,7 +11,7 @@ # 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 +# "addendums" that give useful information about a PR that is 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. @@ -65,7 +65,7 @@ build: **/*.mk,\ *.m4,\ docs/INSTALL-CMAKE.md,\ - lib/curl_config.h.cmake,\ + lib/curl_config-cmake.h.in,\ lib/libcurl*.in,\ CMake/**,\ CMakeLists.txt,\ @@ -98,7 +98,7 @@ cmake: **/CMakeLists.txt,\ CMake/**,\ docs/INSTALL-CMAKE.md,\ - lib/curl_config.h.cmake,\ + lib/curl_config-cmake.h.in,\ tests/cmake/**\ }" @@ -162,9 +162,9 @@ cryptography: docs/libcurl/opts/CURLOPT_EGDSOCKET*,\ lib/*sha256*,\ lib/*sha512*,\ - lib/curl_des.*,\ lib/curl_hmac.*,\ lib/curl_md?.*,\ + lib/curl_ntlm_core.*,\ lib/md?.*,\ lib/rand.*\ }" @@ -451,6 +451,7 @@ TLS: - all: - changed-files: - any-glob-to-all-files: "{\ + CMake/FindGnuTLS.cmake,\ CMake/FindMbedTLS.cmake,\ CMake/FindWolfSSL.cmake,\ CMake/FindRustls.cmake,\ diff --git a/.github/scripts/badwords.ok b/.github/scripts/badwords.ok new file mode 100644 index 000000000000..fe2d9cfaf1ed --- /dev/null +++ b/.github/scripts/badwords.ok @@ -0,0 +1,7 @@ +# Copyright (C) Daniel Stenberg, , et al. +# +# SPDX-License-Identifier: curl +# +# whitelisted uses of bad words +# file:[line]:rule +docs/FAQ.md::\bwill\b diff --git a/.github/scripts/badwords.pl b/.github/scripts/badwords.pl index bd66f331669b..1fde5ec4730f 100755 --- a/.github/scripts/badwords.pl +++ b/.github/scripts/badwords.pl @@ -20,6 +20,29 @@ my @whitelist; my %alt; my %exactcase; +my $skip_indented = 1; + +if($ARGV[0] eq "-a") { + shift @ARGV; + $skip_indented = 0; +} +my %wl; +if($ARGV[0] eq "-w") { + shift @ARGV; + my $file = shift @ARGV; + open(W, "<$file") or die "Cannot open '$file': $!"; + while() { + if(/^#/) { + # allow #-comments + next; + } + if(/^([^:]*):(\d*):(.*)/) { + $wl{"$1:$2:$3"}=1; + #print STDERR "whitelisted $1:$2:$3\n"; + } + } + close(W); +} my @w; while() { @@ -30,7 +53,7 @@ if($_ =~ /^---(.*)/) { push @whitelist, $1; } - elsif($_ =~ /^([^:=]*)([:=])(.*)/) { + elsif($_ =~ /^(.*)([:=])(.*)/) { my ($bad, $sep, $better)=($1, $2, $3); push @w, $bad; $alt{$bad} = $better; @@ -50,7 +73,7 @@ sub file { my $in = $_; $l++; chomp $in; - if($in =~ /^ /) { + if($skip_indented && $in =~ /^ /) { next; } # remove the link part @@ -67,8 +90,22 @@ sub file { ($in =~ /^(.*)$w/ && $case) ) { my $p = $1; my $c = length($p)+1; + + my $ch = "$f:$l:$w"; + if($wl{$ch}) { + # whitelisted filename + line + word + print STDERR "$ch found but whitelisted\n"; + next; + } + $ch = $f . "::" . $w; + if($wl{$ch}) { + # whitelisted filename + word + print STDERR "$ch found but whitelisted\n"; + next; + } + print STDERR "$f:$l:$c: error: found bad word \"$w\"\n"; - printf STDERR " %4d | $in\n", $l; + printf STDERR " %4d | %s\n", $l, $in; printf STDERR " | %*s^%s\n", length($p), " ", "~" x (length($w)-1); printf STDERR " maybe use \"%s\" instead?\n", $alt{$w}; @@ -79,9 +116,11 @@ sub file { close(F); } -my @files = @ARGV; - -foreach my $each (@files) { +my @filemasks = @ARGV; +open(my $git_ls_files, '-|', 'git', 'ls-files', '--', @filemasks) or die "Failed running git ls-files: $!"; +while(my $each = <$git_ls_files>) { + chomp $each; file($each); } +close $git_ls_files; exit $errors; diff --git a/.github/scripts/badwords.txt b/.github/scripts/badwords.txt index 741e5376fced..c5f91795dc07 100644 --- a/.github/scripts/badwords.txt +++ b/.github/scripts/badwords.txt @@ -3,73 +3,93 @@ # SPDX-License-Identifier: curl # back-end:backend -e-mail:email +\be-mail[^/]:email run-time:runtime set-up:setup tool chain:toolchain tool-chain:toolchain wild-card:wildcard wild card:wildcard +\bthread ?safe[^."t]:thread-safe +\bthread ?unsafe[^."t]:thread-unsafe +multi ?thread:multi-thread +\bit's:it is +aren't:are not +can't:cannot +could've:could have +couldn't:could not +didn't:did not +doesn't:does not +don't:do not +haven't:have not +i'd:I would +i'll:I will i'm:I am -you've:You have -we've:we have -we're:we are -we'll:we will -we'd:we would -they've:They have -they're:They are -they'll:They will +i've:I have +isn't:is not +it'd:it would +it'll:it will +might've:might have +needn't:need not +should've:should have +shouldn't:should not +that's:that is +there's:there is they'd:They would -you've:you have +they'll:They will +they're:They are +they've:They have +this'll:this will +wasn't:was not +we'd:we would +we'll:we will +we're:we are +we've:we have +weren't:were not +won't:will not +would've:would have +wouldn't:would not you'd:you would you'll:you will you're:you are -should've:should have -don't=do not -could've:could have -doesn't:does not -isn't:is not -aren't:are not +you've:you have a html: an html a http: an http a ftp: an ftp a IPv4: an IPv4 a IPv6: an IPv6 - url =URL -internet\b=Internet + url [^=]=URL +[^/]internet\b=Internet isation:ization -\bit's:it is -it'd:it would -there's:there is [^.]\. And: Rewrite it somehow? ^(And|So|But) = Rewrite it somehow? \. But: Rewrite it somehow? \. So : Rewrite without "so" ? - dir :directory -can't:cannot -that's:that is + dir [^=]=directory + Dir [^=]=Directory +sub-director:subdirector web page:webpage host name\b:hostname host names\b:hostnames -file name\b:filename +[^;<]file name\b:filename file names\b:filenames \buser name\b:username \buser names\b:usernames \bpass phrase:passphrase -didn't:did not -doesn't:does not -won't:will not -couldn't:could not \bwill\b:rewrite to present tense -\b32bit=32-bit -\b64bit=64-bit -32 bit\b=32-bit -64 bit\b=64-bit +\b32bit:32-bit +\b64bit:64-bit +32 bit\b:32-bit +64 bit\b:64-bit 64-bits:64 bits or 64-bit 32-bits:32 bits or 32-bit \bvery\b:rephrase using an alternative word \bCurl\b=curl +\bcURL\b=curl \bLibcurl\b=libcurl +\bLibCurl\b=libcurl ---WWW::Curl ---NET::Curl ---Curl Corporation +\bmanpages[^./;=&{:-]:man pages +\bmanpage[^si./;=&{:-]:man page diff --git a/.github/scripts/cleancmd.pl b/.github/scripts/cleancmd.pl index 7b79c2e65aee..06b38f102213 100755 --- a/.github/scripts/cleancmd.pl +++ b/.github/scripts/cleancmd.pl @@ -16,7 +16,7 @@ my @asyms; open(S, "<./docs/libcurl/symbols-in-versions") - || die "can't find symbols-in-versions"; + || die "cannot find symbols-in-versions"; while() { if(/^([^ ]*) /) { push @asyms, $1; @@ -30,7 +30,7 @@ ); open(O, "<./docs/options-in-versions") - || die "can't find options-in-versions"; + || die "cannot find options-in-versions"; while() { chomp; if(/^([^ ]+)/) { @@ -50,7 +50,7 @@ close(O); open(C, "<./.github/scripts/spellcheck.curl") - || die "can't find spellcheck.curl"; + || die "cannot find spellcheck.curl"; while() { if(/^\#/) { next; @@ -99,7 +99,7 @@ sub process { # *italics* $l =~ s/\*(\S.*?)\*//g; - # strip out https URLs, we don't want them spellchecked + # strip out https URLs, we do not want them spellchecked $l =~ s!https://[a-z0-9\#_/.-]+!!gi; $out .= $l; @@ -119,6 +119,10 @@ sub process { } } -for my $f (@ARGV) { +my @filemasks = @ARGV; +open(my $git_ls_files, '-|', 'git', 'ls-files', '--', @filemasks) or die "Failed running git ls-files: $!"; +while(my $f = <$git_ls_files>) { + chomp $f; process($f); } +close $git_ls_files; diff --git a/.github/scripts/cmp-config.pl b/.github/scripts/cmp-config.pl index 3ad0570e2839..e831a97211a5 100755 --- a/.github/scripts/cmp-config.pl +++ b/.github/scripts/cmp-config.pl @@ -68,7 +68,6 @@ '#define HAVE_OPENSSL_PEM_H 1' => 1, '#define HAVE_OPENSSL_RSA_H 1' => 1, '#define HAVE_OPENSSL_SSL_H 1' => 1, - '#define HAVE_OPENSSL_X509_H 1' => 1, '#define HAVE_QUICHE_H 1' => 1, '#define HAVE_SSL_SET_QUIC_TLS_CBS 1' => 1, '#define HAVE_SSL_SET_QUIC_USE_LEGACY_CODEPOINT 1' => 1, @@ -136,6 +135,5 @@ sub grepit { } } - # return the exit code from diff exit system("diff -u /tmp/autotools /tmp/cmake") >> 8; diff --git a/.github/scripts/codespell-ignore.words b/.github/scripts/codespell-ignore.words index fa8a432b95aa..1a5e106400a6 100644 --- a/.github/scripts/codespell-ignore.words +++ b/.github/scripts/codespell-ignore.words @@ -7,7 +7,7 @@ bu clen CNA hel -htpt +htpts inout PASE passwor diff --git a/.github/scripts/codespell.sh b/.github/scripts/codespell.sh index bbbbef571968..dfb6467535e6 100755 --- a/.github/scripts/codespell.sh +++ b/.github/scripts/codespell.sh @@ -7,7 +7,7 @@ set -eu cd "$(dirname "${0}")"/../.. -# shellcheck disable=SC2046 +git ls-files -z | xargs -0 -r \ codespell \ --skip '.github/scripts/pyspelling.words' \ --skip '.github/scripts/typos.toml' \ @@ -16,4 +16,4 @@ codespell \ --skip 'scripts/wcurl' \ --ignore-regex '.*spellchecker:disable-line' \ --ignore-words '.github/scripts/codespell-ignore.words' \ - $(git ls-files) + -- diff --git a/.github/scripts/pyspelling.words b/.github/scripts/pyspelling.words index a5c28091301f..6b755d2043d7 100644 --- a/.github/scripts/pyspelling.words +++ b/.github/scripts/pyspelling.words @@ -53,6 +53,7 @@ axTLS backend backends backoff +backtick backticks balancers Baratov @@ -149,7 +150,6 @@ CSeq csh cshrc CTRL -cURL CURLcode curldown CURLE @@ -172,8 +172,10 @@ dbg Debian DEBUGBUILD decrypt +decrypted decrypting deepcode +defacto DELE DER dereference @@ -202,6 +204,7 @@ DLLs DNS dns dnsop +DNSSEC DoH DoT doxygen @@ -215,6 +218,7 @@ dynbuf EAGAIN EBCDIC ECC +ECCN ECDHE ECH ECHConfig @@ -245,6 +249,7 @@ et etag ETag ETags +exa exe executables EXPN @@ -258,6 +263,7 @@ Fedora Feltzing ffi filesize +filesystem FindCURL FLOSS fnmatch @@ -299,6 +305,7 @@ Ghedini giga Gisle Glesys +glibc globbed globbing gmail @@ -380,6 +387,7 @@ imap IMAPS imaps impacket +implementers init initializer inlined @@ -418,6 +426,7 @@ kerberos Keychain keychain KiB +kibibyte kickstart Kirei Knauf @@ -432,7 +441,9 @@ ldap LDAPS ldaps LF +LGPL LGTM +libbacktrace libbrotlidec libc libcurl @@ -462,6 +473,7 @@ libWebSocket libz libzstd LineageOS +linter linux lldb ln @@ -492,6 +504,7 @@ Mavrogiannopoulos Mbed mbedTLS md +mebibyte Meglio memdebug MesaLink @@ -564,6 +577,7 @@ Necko NetBSD netrc netstat +NetWare Netware NFS nghttp @@ -707,6 +721,7 @@ ROADMAP Roadmap Rockbox roffit +RPC RPG RR RRs @@ -794,6 +809,7 @@ sprintf src SRP SRWLOCK +SSI SSL ssl SSLeay @@ -889,6 +905,7 @@ UI UID UIDL Ultrix +umask Unary unassign UNC @@ -954,12 +971,13 @@ watchOS WAV WB wcurl -web page WebDAV WebOS webpage +webpages WebSocket WEBSOCKET +Wget WHATWG whitespace Whitespaces @@ -978,7 +996,9 @@ www Xbox XDG xdigit +XHTML Xilinx +xmllint XP Xtensa XYZ diff --git a/.github/scripts/pyspelling.yaml b/.github/scripts/pyspelling.yaml index 8e26b76189bc..bb0585ab7ab8 100644 --- a/.github/scripts/pyspelling.yaml +++ b/.github/scripts/pyspelling.yaml @@ -30,4 +30,4 @@ matrix: - 'strong' - 'em' sources: - - '**/*.md|!docs/BINDINGS.md|!docs/DISTROS.md|!docs/CIPHERS-TLS12.md|!docs/wcurl.md' + - '**/*.md|!docs/BINDINGS.md|!docs/DISTROS.md|!docs/CIPHERS-TLS12.md|!docs/wcurl.md|!tests/data/data*.md' diff --git a/.github/scripts/randcurl.pl b/.github/scripts/randcurl.pl index b085d2ef13d5..f9c24d90db6c 100755 --- a/.github/scripts/randcurl.pl +++ b/.github/scripts/randcurl.pl @@ -116,7 +116,6 @@ sub randarg { '26' => 1, ); - sub runone { my $a; my $nargs = getnum(60) + 1; diff --git a/.github/scripts/requirements-docs.txt b/.github/scripts/requirements-docs.txt index bd50e5010efb..6850461de7bc 100644 --- a/.github/scripts/requirements-docs.txt +++ b/.github/scripts/requirements-docs.txt @@ -2,4 +2,4 @@ # # SPDX-License-Identifier: curl -pyspelling==2.11 +pyspelling==2.12.1 diff --git a/tests/data/.gitattributes b/.github/scripts/requirements-proselint.txt similarity index 83% rename from tests/data/.gitattributes rename to .github/scripts/requirements-proselint.txt index bb1b92830695..189610944297 100644 --- a/tests/data/.gitattributes +++ b/.github/scripts/requirements-proselint.txt @@ -2,4 +2,4 @@ # # SPDX-License-Identifier: curl -test* -crlf +proselint==0.16.0 diff --git a/.github/scripts/requirements.txt b/.github/scripts/requirements.txt index 4533b2cfd7d9..b6a7e5e10ed6 100644 --- a/.github/scripts/requirements.txt +++ b/.github/scripts/requirements.txt @@ -5,5 +5,5 @@ cmakelang==0.6.13 codespell==2.4.1 pytype==2024.10.11 -reuse==6.1.2 -ruff==0.14.0 +reuse==6.2.0 +ruff==0.14.9 diff --git a/.github/scripts/shellcheck.sh b/.github/scripts/shellcheck.sh index 66590ec6c7c3..59b49131ac4b 100755 --- a/.github/scripts/shellcheck.sh +++ b/.github/scripts/shellcheck.sh @@ -3,7 +3,11 @@ # # SPDX-License-Identifier: curl -# shellcheck disable=SC2046 -shellcheck --exclude=1091 \ +set -eu + +cd "$(dirname "${0}")"/../.. + +git grep -z -l -E '^#!(/usr/bin/env bash|/bin/sh|/bin/bash)' | xargs -0 -r \ +shellcheck --exclude=1091,2248 \ --enable=avoid-nullary-conditions,deprecate-which \ - $(grep -l -E '^#!(/usr/bin/env bash|/bin/sh|/bin/bash)' $(git ls-files)) + -- diff --git a/.github/scripts/spacecheck.pl b/.github/scripts/spacecheck.pl index fbd064db3ba2..f06766570c75 100755 --- a/.github/scripts/spacecheck.pl +++ b/.github/scripts/spacecheck.pl @@ -31,10 +31,7 @@ "Makefile\\.(am|example)\$", "/mkfile", "\\.sln\$", - "^tests/data/test", -); - -my @mixed_eol = ( + "^tests/data/data1706-stdout.txt", "^tests/data/test", ); @@ -42,8 +39,11 @@ "\\.(bat|sln)\$", ); -my @space_at_eol = ( +my @double_empty_lines = ( + "^lib/.+\\.(c|h)\$", + "^packages/", "^tests/data/test", + "\\.(m4|py)\$", ); my @non_ascii_allowed = ( @@ -96,41 +96,38 @@ sub eol_detect { my $issues = 0; -open my $git_ls_files, '-|', 'git ls-files' or die "Failed running git ls-files: $!"; +open(my $git_ls_files, '-|', 'git ls-files') or die "Failed running git ls-files: $!"; while(my $filename = <$git_ls_files>) { chomp $filename; - open my $fh, '<', $filename or die "Cannot open '$filename': $!"; + open(my $fh, '<', $filename) or die "Cannot open '$filename': $!"; my $content = do { local $/; <$fh> }; close $fh; my @err = (); if(!fn_match($filename, @tabs) && - $content =~ /\t/) { + $content =~ /\t/) { push @err, "content: has tab"; } my $eol = eol_detect($content); - if($eol eq "" && - !fn_match($filename, @mixed_eol)) { + if($eol eq "") { push @err, "content: has mixed EOL types"; } if($eol ne "crlf" && - fn_match($filename, @need_crlf)) { + fn_match($filename, @need_crlf)) { push @err, "content: must use CRLF EOL for this file type"; } if($eol ne "lf" && $content ne "" && - !fn_match($filename, @need_crlf) && - !fn_match($filename, @mixed_eol)) { + !fn_match($filename, @need_crlf)) { push @err, "content: must use LF EOL for this file type"; } - if(!fn_match($filename, @space_at_eol) && - $content =~ /[ \t]\n/) { + if($content =~ /[ \t]\n/) { my $line; for my $l (split(/\n/, $content)) { $line++; @@ -141,20 +138,27 @@ sub eol_detect { } if($content ne "" && - $content !~ /\n\z/) { + $content !~ /\n\z/) { push @err, "content: has no EOL at EOF"; } if($content =~ /\n\n\z/ || - $content =~ /\r\n\r\n\z/) { + $content =~ /\r\n\r\n\z/) { push @err, "content: has multiple EOL at EOF"; } if($content =~ /\n\n\n\n/ || - $content =~ /\r\n\r\n\r\n\r\n/) { + $content =~ /\r\n\r\n\r\n\r\n/) { push @err, "content: has 3 or more consecutive empty lines"; } + if(!fn_match($filename, @double_empty_lines)) { + if($content =~ /\n\n\n/ || + $content =~ /\r\n\r\n\r\n/) { + push @err, "content: has 2 consecutive empty lines"; + } + } + if($content =~ /([\x00-\x08\x0b\x0c\x0e-\x1f\x7f])/) { push @err, "content: has binary contents"; } diff --git a/.github/scripts/typos.toml b/.github/scripts/typos.toml index 28dcad73bec4..2b12004f489d 100644 --- a/.github/scripts/typos.toml +++ b/.github/scripts/typos.toml @@ -4,12 +4,12 @@ [default] extend-ignore-identifiers-re = [ - "^(ba|pn|PN|UE)$", + "^(ba|fo|pn|PN|UE)$", "^(CNA|ser)$", - "^(ECT0|ECT1|HELO|htpt|PASE)$", + "^(ECT0|ECT1|HELO|htpts|PASE)$", "^[A-Za-z0-9_-]*(EDE|GOST)[A-Z0-9_-]*$", # ciphers "^0x[0-9a-fA-F]+FUL$", # unsigned long hex literals ending with 'F' - "^(eyeballers|HELO_smtp|optin|passin|perfec|SMTP_HELO)$", + "^(eyeballers|HELO_smtp|Januar|optin|passin|perfec|SMTP_HELO)$", "^(clen|req_clen|smtp_perform_helo|smtp_state_helo_resp|Tru64|_stati64)$", "secur32", "proxys", # this should be limited to tests/http/*. Short for secure proxy. diff --git a/.github/scripts/verify-synopsis.pl b/.github/scripts/verify-synopsis.pl index 1c6b00b60bd1..19fbc31a7c81 100755 --- a/.github/scripts/verify-synopsis.pl +++ b/.github/scripts/verify-synopsis.pl @@ -39,7 +39,6 @@ sub testcompile { return $rc; } - sub extract { my($f) = @_; my $syn = 0; diff --git a/.github/scripts/yamlcheck.sh b/.github/scripts/yamlcheck.sh index 2431c97abc7a..4bdeff45cb96 100755 --- a/.github/scripts/yamlcheck.sh +++ b/.github/scripts/yamlcheck.sh @@ -5,9 +5,11 @@ set -eu -# shellcheck disable=SC2046 +cd "$(dirname "${0}")"/../.. + +git ls-files '*.yaml' '*.yml' -z | xargs -0 -r \ yamllint \ --format standard \ --strict \ - --config-data "$(dirname "$0")/yamlcheck.yaml" \ - $(git ls-files '*.yaml' '*.yml') + --config-data .github/scripts/yamlcheck.yaml \ + -- diff --git a/.github/stale.yml b/.github/stale.yml index dc239b56ce72..69a822e78be8 100644 --- a/.github/stale.yml +++ b/.github/stale.yml @@ -6,7 +6,7 @@ daysUntilStale: 180 # Number of days of inactivity before a stale issue is closed daysUntilClose: 14 -# Issues with these labels will never be considered stale +# Issues with these labels are never considered stale exemptLabels: - pinned - security diff --git a/.github/workflows/checkdocs.yml b/.github/workflows/checkdocs.yml index 58f5f29f8b4c..8fde2c536c34 100644 --- a/.github/workflows/checkdocs.yml +++ b/.github/workflows/checkdocs.yml @@ -14,8 +14,8 @@ name: 'Docs' - '*/ci' paths: - '.github/workflows/checkdocs.yml' - - '.github/scripts/mdlinkcheck' - - '/scripts/**' + - '.github/scripts/**' + - 'scripts/**' - '**.md' - 'docs/*' pull_request: @@ -24,7 +24,7 @@ name: 'Docs' paths: - '.github/workflows/checkdocs.yml' - '.github/scripts/**' - - '.github/scripts/mdlinkcheck' + - 'scripts/**' - '**.md' - 'docs/*' @@ -35,83 +35,68 @@ concurrency: permissions: {} jobs: - # proselint: - # name: 'proselint' - # runs-on: ubuntu-latest - # steps: - # - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - # with: - # persist-credentials: false - # - # - name: 'install prereqs' - # run: | - # sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list - # sudo apt-get -o Dpkg::Use-Pty=0 update - # sudo rm -f /var/lib/man-db/auto-update - # sudo apt-get -o Dpkg::Use-Pty=0 install python3-proselint - # - # # config file help: https://github.com/amperser/proselint/ - # - name: 'create proselint config' - # run: | - # cat < ~/.proselintrc.json - # { - # "checks": { - # "typography.diacritical_marks": false, - # "typography.symbols": false, - # "annotations.misc": false, - # "security.password": false, - # "misc.annotations": false - # } - # } - # JSON - # - # - name: 'trim headers off all *.md files' - # run: git ls-files -z '*.md' | xargs -0 -n1 .github/scripts/trimmarkdownheader.pl - # - # - name: 'check prose' - # run: git ls-files -z '*.md' | grep -Evz 'CHECKSRC\.md|DISTROS\.md|curl_mprintf\.md|CURLOPT_INTERFACE\.md|interface\.md' | xargs -0 proselint -- README - # - # # This is for CHECKSRC and files with aggressive exclamation mark needs - # - name: 'create second proselint config' - # run: | - # cat < ~/.proselintrc.json - # { - # "checks": { - # "typography.diacritical_marks": false, - # "typography.symbols": false, - # "typography.exclamation": false, - # "lexical_illusions.misc": false, - # "annotations.misc": false - # } - # } - # JSON - # - # - name: 'check special prose' - # run: proselint docs/internals/CHECKSRC.md docs/libcurl/curl_mprintf.md docs/libcurl/opts/CURLOPT_INTERFACE.md docs/cmdline-opts/interface.md - - linkcheck: - name: 'linkcheck' + # config file help: https://github.com/amperser/proselint/ + proselint: + name: 'proselint' runs-on: ubuntu-latest steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - - name: 'mdlinkcheck' - run: ./scripts/mdlinkcheck + - name: 'install prereqs' + run: | + python3 -m venv ~/venv + ~/venv/bin/pip --disable-pip-version-check --no-input --no-cache-dir install --progress-bar off --prefer-binary -r .github/scripts/requirements-proselint.txt + + - name: 'trim headers off all *.md files' + run: git ls-files '*.md' -z | xargs -0 -n1 .github/scripts/trimmarkdownheader.pl + + - name: 'check prose' + run: | + cat < ~/.proselintrc.json + { + "checks": { + "annotations.misc": false, + "lexical_illusions": false, + "misc.annotations": false, + "redundancy.misc.garner": false, + "security.password": false, + "spelling.ve_of": false, + "typography.diacritical_marks": false, + "typography.symbols": false + } + } + JSON + source ~/venv/bin/activate + git ls-files README '*.md' -z | grep -Evz '(CHECKSRC|DISTROS|CURLOPT_INTERFACE|interface)\.md' | xargs -0 proselint check -- + + - name: 'check special prose' # For CHECKSRC and files with aggressive exclamation mark needs + run: | + cat < ~/.proselintrc.json + { + "checks": { + "annotations.misc": false, + "lexical_illusions": false, + "typography.diacritical_marks": false, + "typography.punctuation.exclamation": false, + "typography.symbols": false + } + } + JSON + source ~/venv/bin/activate + proselint check docs/internals/CHECKSRC.md docs/libcurl/opts/CURLOPT_INTERFACE.md docs/cmdline-opts/interface.md pyspelling: name: 'pyspelling' runs-on: ubuntu-latest steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - name: 'trim all *.md files in docs/' - run: | - # shellcheck disable=SC2046 - .github/scripts/cleancmd.pl $(find docs -name '*.md') + run: .github/scripts/cleancmd.pl 'docs/*.md' - name: 'install' run: | @@ -135,14 +120,12 @@ jobs: name: 'badwords, synopsis' runs-on: ubuntu-latest steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - name: 'badwords' - run: | - # shellcheck disable=SC2046 - .github/scripts/badwords.pl < .github/scripts/badwords.txt $(git ls-files '**.md') docs/TODO docs/KNOWN_BUGS packages/OS400/README.OS400 + run: .github/scripts/badwords.pl -w .github/scripts/badwords.ok '**.md' packages/OS400/README.OS400 < .github/scripts/badwords.txt - name: 'verify synopsis' run: .github/scripts/verify-synopsis.pl docs/libcurl/curl*.md @@ -151,7 +134,7 @@ jobs: name: 'man-examples' runs-on: ubuntu-latest steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false @@ -163,7 +146,7 @@ jobs: runs-on: ubuntu-24.04-arm timeout-minutes: 5 steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false diff --git a/.github/workflows/checksrc.yml b/.github/workflows/checksrc.yml index a0337904f2c7..7da9df8faca4 100644 --- a/.github/workflows/checksrc.yml +++ b/.github/workflows/checksrc.yml @@ -16,7 +16,6 @@ name: 'Source' - 'appveyor.*' - 'Dockerfile' - 'plan9/**' - - 'tests/data/**' pull_request: branches: - master @@ -25,7 +24,10 @@ name: 'Source' - 'appveyor.*' - 'Dockerfile' - 'plan9/**' - - 'tests/data/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} + cancel-in-progress: true permissions: {} @@ -34,7 +36,7 @@ jobs: name: 'checksrc' runs-on: ubuntu-latest steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false @@ -45,11 +47,11 @@ jobs: name: 'spellcheck, linters, REUSE' runs-on: ubuntu-latest steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - - name: 'install' + - name: 'install prereqs' run: | python3 -m venv ~/venv ~/venv/bin/pip --disable-pip-version-check --no-input --no-cache-dir install --progress-bar off --prefer-binary \ @@ -69,6 +71,7 @@ jobs: .github/scripts/codespell.sh - name: 'typos' + timeout-minutes: 2 run: | HOMEBREW_NO_AUTO_UPDATE=1 /home/linuxbrew/.linuxbrew/bin/brew install typos-cli eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" @@ -87,7 +90,7 @@ jobs: - name: 'pytype' run: | source ~/venv/bin/activate - find . -name '*.py' -exec pytype -j auto -k {} + + find . -name '*.py' -exec pytype -j auto -k -- {} + - name: 'ruff' run: | @@ -99,10 +102,6 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 3 steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - with: - persist-credentials: false - - name: 'install pmccabe' run: | sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list @@ -111,18 +110,43 @@ jobs: sudo apt-get -o Dpkg::Use-Pty=0 install \ pmccabe + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + persist-credentials: false + - name: 'check scores' run: ./scripts/top-complexity + xmllint: + name: 'xmllint' + runs-on: ubuntu-latest + timeout-minutes: 3 + steps: + - name: 'install prereqs' + run: | + sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list + sudo apt-get -o Dpkg::Use-Pty=0 update + sudo rm -f /var/lib/man-db/auto-update + sudo apt-get -o Dpkg::Use-Pty=0 install \ + libxml2-utils + + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + persist-credentials: false + + - name: 'check' + run: git grep -z -i -l -E '^<\?xml' | xargs -0 -r xmllint --output /dev/null + miscchecks: name: 'misc checks' runs-on: ubuntu-latest timeout-minutes: 5 steps: - name: 'install prereqs' - run: HOMEBREW_NO_AUTO_UPDATE=1 /home/linuxbrew/.linuxbrew/bin/brew install shellcheck zizmor + timeout-minutes: 2 + run: HOMEBREW_NO_AUTO_UPDATE=1 /home/linuxbrew/.linuxbrew/bin/brew install actionlint shellcheck zizmor - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false @@ -131,7 +155,14 @@ jobs: GH_TOKEN: '${{ secrets.GITHUB_TOKEN }}' run: | eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" - zizmor --pedantic .github/workflows/*.yml + zizmor --pedantic .github/workflows/*.yml .github/dependabot.yml + + - name: 'actionlint' + run: | + eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" + export SHELLCHECK_OPTS='--exclude=1090,1091,2086,2153 --enable=avoid-nullary-conditions,deprecate-which' + actionlint --version + actionlint --ignore matrix .github/workflows/*.yml - name: 'shellcheck CI' run: | @@ -151,9 +182,7 @@ jobs: - name: 'yamlcheck' run: .github/scripts/yamlcheck.sh - # we allow some extra in source code - name: 'badwords' run: | - # shellcheck disable=SC2046 - grep -Ev '(\\bwill| url | dir )' .github/scripts/badwords.txt | \ - .github/scripts/badwords.pl $(git ls-files -- src lib include) + # we allow some extra in source code + grep -Ev '(\\bwill| But: | So : )' .github/scripts/badwords.txt | .github/scripts/badwords.pl -a src lib include docs/examples diff --git a/.github/workflows/checkurls.yml b/.github/workflows/checkurls.yml new file mode 100644 index 000000000000..4a14a930d50d --- /dev/null +++ b/.github/workflows/checkurls.yml @@ -0,0 +1,40 @@ +# Copyright (C) Daniel Stenberg, , et al. +# +# SPDX-License-Identifier: curl + +name: 'URLs' + +'on': + push: + branches: + - master + - '*/ci' + pull_request: + branches: + - master + schedule: + - cron: '10 5 * * *' + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} + cancel-in-progress: true + +permissions: {} + +jobs: + linkcheck: + if: ${{ github.repository_owner == 'curl' || github.event_name != 'schedule' }} + name: 'linkcheck' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + persist-credentials: false + + - name: 'mdlinkcheck (dry run)' + if: ${{ github.event_name != 'schedule' }} + run: ./scripts/mdlinkcheck --dry-run + + - name: 'mdlinkcheck' + if: ${{ github.event_name == 'schedule' }} + run: ./scripts/mdlinkcheck diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 58eaa35be5ba..7f4ff2f20dd6 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -32,31 +32,34 @@ name: 'CodeQL' - cron: '0 0 * * 4' concurrency: - group: ${{ github.workflow }} + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} + cancel-in-progress: true permissions: {} jobs: gha_python: + if: ${{ github.repository_owner == 'curl' || github.event_name != 'schedule' }} name: 'GHA and Python' runs-on: ubuntu-latest permissions: security-events: write # To create/update security events steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - name: 'initialize' - uses: github/codeql-action/init@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7 + uses: github/codeql-action/init@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8 with: languages: actions, python queries: security-extended - name: 'perform analysis' - uses: github/codeql-action/analyze@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7 + uses: github/codeql-action/analyze@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8 c: + if: ${{ github.repository_owner == 'curl' || github.event_name != 'schedule' }} name: 'C' runs-on: ${{ matrix.platform == 'Linux' && 'ubuntu-latest' || 'windows-2022' }} permissions: @@ -79,12 +82,12 @@ jobs: libnghttp2-dev libldap-dev libkrb5-dev librtmp-dev libgnutls28-dev libwolfssl-dev HOMEBREW_NO_AUTO_UPDATE=1 /home/linuxbrew/.linuxbrew/bin/brew install c-ares gsasl libnghttp3 libngtcp2 mbedtls rustls-ffi - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - name: 'initialize' - uses: github/codeql-action/init@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7 + uses: github/codeql-action/init@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8 with: languages: cpp build-mode: manual @@ -105,29 +108,27 @@ jobs: # MultiSSL export PKG_CONFIG_PATH; PKG_CONFIG_PATH="$(brew --prefix c-ares)/lib/pkgconfig:$(brew --prefix mbedtls)/lib/pkgconfig:$(brew --prefix rustls-ffi)/lib/pkgconfig:$(brew --prefix gsasl)/lib/pkgconfig" - cmake -B _bld1 -G Ninja -DENABLE_DEBUG=ON \ + cmake -B _bld1 -G Ninja -DCURL_DISABLE_TYPECHECK=ON -DENABLE_DEBUG=ON \ -DCURL_USE_GNUTLS=ON -DCURL_USE_MBEDTLS=ON -DCURL_USE_RUSTLS=ON -DCURL_USE_WOLFSSL=ON \ -DUSE_LIBRTMP=ON -DCURL_USE_GSASL=ON -DCURL_USE_GSSAPI=ON -DUSE_SSLS_EXPORT=ON -DUSE_ECH=ON -DENABLE_ARES=ON \ -DCURL_DISABLE_VERBOSE_STRINGS=ON cmake --build _bld1 - cmake --build _bld1 --target curlinfo - cmake --build _bld1 --target servers - cmake --build _bld1 --target tunits - cmake --build _bld1 --target units + cmake --build _bld1 --target testdeps cmake --build _bld1 --target curl-examples-build # HTTP/3 export PKG_CONFIG_PATH; PKG_CONFIG_PATH="$(brew --prefix libnghttp3)/lib/pkgconfig:$(brew --prefix libngtcp2)/lib/pkgconfig:$(brew --prefix gsasl)/lib/pkgconfig" - cmake -B _bld2 -G Ninja \ + cmake -B _bld2 -G Ninja -DCURL_DISABLE_TYPECHECK=ON \ -DCURL_USE_OPENSSL=ON -DOPENSSL_ROOT_DIR="$(brew --prefix openssl)" -DUSE_NGTCP2=ON \ -DCURL_USE_LIBSSH2=OFF -DCURL_USE_LIBSSH=ON \ -DUSE_LIBRTMP=ON -DCURL_USE_GSASL=ON -DCURL_USE_GSSAPI=ON -DUSE_SSLS_EXPORT=ON cmake --build _bld2 - cmake --build _bld2 --target servers + cmake --build _bld2 --target testdeps + cmake --build _bld2 --target curl-examples-build _bld1/src/curl --disable --version _bld2/src/curl --disable --version fi - name: 'perform analysis' - uses: github/codeql-action/analyze@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7 + uses: github/codeql-action/analyze@1b168cd39490f61582a9beae412bb7057a6b2c4e # v4.31.8 diff --git a/.github/workflows/configure-vs-cmake.yml b/.github/workflows/configure-vs-cmake.yml index 5c35051f6a34..52c808db4461 100644 --- a/.github/workflows/configure-vs-cmake.yml +++ b/.github/workflows/configure-vs-cmake.yml @@ -12,7 +12,7 @@ name: 'configure-vs-cmake' - '**/*.m4' - '**/CMakeLists.txt' - 'CMake/**' - - 'lib/curl_config.h.cmake' + - 'lib/curl_config-cmake.h.in' - 'tests/cmake/**' - '.github/scripts/cmp-config.pl' - '.github/workflows/configure-vs-cmake.yml' @@ -25,11 +25,15 @@ name: 'configure-vs-cmake' - '**/*.m4' - '**/CMakeLists.txt' - 'CMake/**' - - 'lib/curl_config.h.cmake' + - 'lib/curl_config-cmake.h.in' - 'tests/cmake/**' - '.github/scripts/cmp-config.pl' - '.github/workflows/configure-vs-cmake.yml' +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} + cancel-in-progress: true + permissions: {} jobs: @@ -37,7 +41,7 @@ jobs: name: 'Linux' runs-on: ubuntu-latest steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false @@ -77,6 +81,7 @@ jobs: runs-on: macos-latest steps: - name: 'install packages' + timeout-minutes: 2 run: | # shellcheck disable=SC2181,SC2034 while [[ $? == 0 ]]; do for i in 1 2 3; do if brew update && brew install automake libtool; then break 2; else echo Error: wait to try again; sleep 10; fi; done; false Too many retries; done @@ -84,7 +89,7 @@ jobs: - name: 'toolchain versions' run: echo '::group::brew packages installed'; ls -l /opt/homebrew/opt; echo '::endgroup::' - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false @@ -133,7 +138,7 @@ jobs: sudo rm -f /var/lib/man-db/auto-update sudo apt-get -o Dpkg::Use-Pty=0 install gcc-mingw-w64-x86-64-win32 - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false diff --git a/.github/workflows/curl-for-win.yml b/.github/workflows/curl-for-win.yml index 91b0382a7562..d32bfe7c3386 100644 --- a/.github/workflows/curl-for-win.yml +++ b/.github/workflows/curl-for-win.yml @@ -47,7 +47,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false path: 'curl' @@ -63,12 +63,39 @@ jobs: export CW_GCCSUFFIX='-12' sudo podman image trust set --type reject default sudo podman image trust set --type accept docker.io/library - time podman pull "${DOCKER_IMAGE_STABLE}" + time podman pull "${OCI_IMAGE_DEBIAN_STABLE}" podman images --digests time podman run --volume "$(pwd):$(pwd)" --workdir "$(pwd)" \ --env-file <(env | grep -a -E \ '^(CW_|GITHUB_)') \ - "${DOCKER_IMAGE_STABLE}" \ + "${OCI_IMAGE_DEBIAN_STABLE}" \ + sh -c ./_ci-linux-debian.sh + + linux-glibc-gcc-minimal: # use gcc to minimize installed packages + name: 'Linux gcc glibc minimal' + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 + with: + persist-credentials: false + path: 'curl' + fetch-depth: 8 + - name: 'build' + run: | + git clone --depth 1 https://github.com/curl/curl-for-win + mv curl-for-win/* . + export CW_CONFIG='-main-werror-unitybatch-prefill-zero-osnotls-osnoidn-nohttp-nocurltool-linux-x64-gcc' + export CW_REVISION="${GITHUB_SHA}" + . ./_versions.sh + sudo podman image trust set --type reject default + sudo podman image trust set --type accept docker.io/library + time podman pull "${OCI_IMAGE_DEBIAN}" + podman images --digests + time podman run --volume "$(pwd):$(pwd)" --workdir "$(pwd)" \ + --env-file <(env | grep -a -E \ + '^(CW_|GITHUB_)') \ + "${OCI_IMAGE_DEBIAN}" \ sh -c ./_ci-linux-debian.sh linux-musl-llvm: @@ -76,7 +103,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false path: 'curl' @@ -90,12 +117,12 @@ jobs: . ./_versions.sh sudo podman image trust set --type reject default sudo podman image trust set --type accept docker.io/library - time podman pull "${DOCKER_IMAGE}" + time podman pull "${OCI_IMAGE_DEBIAN}" podman images --digests time podman run --volume "$(pwd):$(pwd)" --workdir "$(pwd)" \ --env-file <(env | grep -a -E \ '^(CW_|GITHUB_)') \ - "${DOCKER_IMAGE}" \ + "${OCI_IMAGE_DEBIAN}" \ sh -c ./_ci-linux-debian.sh mac-clang: @@ -105,7 +132,7 @@ jobs: env: CW_JOBS: '4' steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false path: 'curl' @@ -123,7 +150,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false path: 'curl' @@ -132,25 +159,25 @@ jobs: run: | git clone --depth 1 https://github.com/curl/curl-for-win mv curl-for-win/* . - export CW_CONFIG='-main-werror-unitybatch-win-x64' + export CW_CONFIG='-main-werror-unitybatch-win-x64-noWINE' export CW_REVISION="${GITHUB_SHA}" . ./_versions.sh sudo podman image trust set --type reject default sudo podman image trust set --type accept docker.io/library - time podman pull "${DOCKER_IMAGE}" + time podman pull "${OCI_IMAGE_DEBIAN}" podman images --digests time podman run --volume "$(pwd):$(pwd)" --workdir "$(pwd)" \ --env-file <(env | grep -a -E \ '^(CW_|GITHUB_)') \ - "${DOCKER_IMAGE}" \ + "${OCI_IMAGE_DEBIAN}" \ sh -c ./_ci-linux-debian.sh - win-gcc-libssh-zlibold-x64: - name: 'Windows gcc libssh zlib-classic (x64)' + win-gcc-zlibold-x64: + name: 'Windows gcc zlib-classic (x64)' runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false path: 'curl' @@ -159,15 +186,15 @@ jobs: run: | git clone --depth 1 https://github.com/curl/curl-for-win mv curl-for-win/* . - export CW_CONFIG='-main-werror-unitybatch-win-x64-gcc-libssh1-zlibold' + export CW_CONFIG='-main-werror-unitybatch-win-x64-gcc-zlibold-noWINE' export CW_REVISION="${GITHUB_SHA}" . ./_versions.sh sudo podman image trust set --type reject default sudo podman image trust set --type accept docker.io/library - time podman pull "${DOCKER_IMAGE}" + time podman pull "${OCI_IMAGE_DEBIAN}" podman images --digests time podman run --volume "$(pwd):$(pwd)" --workdir "$(pwd)" \ --env-file <(env | grep -a -E \ '^(CW_|GITHUB_)') \ - "${DOCKER_IMAGE}" \ + "${OCI_IMAGE_DEBIAN}" \ sh -c ./_ci-linux-debian.sh diff --git a/.github/workflows/distcheck.yml b/.github/workflows/distcheck.yml index c6b4e775ebe2..ffd607bcdd0f 100644 --- a/.github/workflows/distcheck.yml +++ b/.github/workflows/distcheck.yml @@ -20,6 +20,7 @@ concurrency: permissions: {} env: + CURL_TEST_MIN: 1450 MAKEFLAGS: -j 5 jobs: @@ -28,7 +29,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false @@ -49,7 +50,7 @@ jobs: - name: 'maketgz' run: SOURCE_DATE_EPOCH=1711526400 ./scripts/maketgz 99.98.97 - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: 'release-tgz' path: 'curl-99.98.97.tar.gz' @@ -75,7 +76,7 @@ jobs: timeout-minutes: 10 needs: maketgz-and-verify-in-tree steps: - - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 + - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: name: 'release-tgz' @@ -99,7 +100,7 @@ jobs: timeout-minutes: 10 needs: maketgz-and-verify-in-tree steps: - - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 + - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: name: 'release-tgz' @@ -125,7 +126,7 @@ jobs: timeout-minutes: 10 needs: maketgz-and-verify-in-tree steps: - - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 + - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: name: 'release-tgz' @@ -149,7 +150,7 @@ jobs: timeout-minutes: 10 needs: maketgz-and-verify-in-tree steps: - - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 + - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: name: 'release-tgz' @@ -170,7 +171,7 @@ jobs: timeout-minutes: 5 needs: maketgz-and-verify-in-tree steps: - - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 + - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: name: 'release-tgz' @@ -192,7 +193,7 @@ jobs: timeout-minutes: 5 needs: maketgz-and-verify-in-tree steps: - - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 + - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: name: 'release-tgz' @@ -214,11 +215,11 @@ jobs: timeout-minutes: 5 needs: maketgz-and-verify-in-tree steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 + - uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: name: 'release-tgz' @@ -230,7 +231,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false @@ -267,7 +268,7 @@ jobs: matrix: image: [ubuntu-latest, macos-latest, windows-2022] steps: - - uses: msys2/setup-msys2@fb197b72ce45fb24f17bf3f807a388985654d1f2 # v2.29.0 + - uses: msys2/setup-msys2@4f806de0a5a7294ffabaff804b38a9b435a73bda # v2.30.0 if: ${{ contains(matrix.image, 'windows') }} with: msystem: mingw64 @@ -279,6 +280,7 @@ jobs: mingw-w64-x86_64-zlib mingw-w64-x86_64-zstd mingw-w64-x86_64-libpsl mingw-w64-x86_64-libssh2 mingw-w64-x86_64-nghttp2 mingw-w64-x86_64-openssl - name: 'install prereqs' + timeout-minutes: 3 run: | if [[ "${MATRIX_IMAGE}" = *'windows'* ]]; then cd ~ @@ -302,7 +304,7 @@ jobs: printf '%s' ~/cmake-"${OLD_CMAKE_VERSION}"-Darwin-x86_64/CMake.app/Contents/bin/cmake > ~/old-cmake-path.txt fi - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false diff --git a/.github/workflows/fuzz.yml b/.github/workflows/fuzz.yml index 1c466160fc77..eb4bd0dc887b 100644 --- a/.github/workflows/fuzz.yml +++ b/.github/workflows/fuzz.yml @@ -35,6 +35,11 @@ name: 'Fuzzer' - 'projects/**' - 'tests/data/**' +concurrency: + # Hard-coded workflow name to avoid colliding with curl-fuzzer's group + group: curl-fuzz-${{ github.event.pull_request.number || github.sha }} + cancel-in-progress: true + permissions: {} jobs: diff --git a/.github/workflows/http3-linux.yml b/.github/workflows/http3-linux.yml index 38d2fb6ac025..ee34fa0ead1d 100644 --- a/.github/workflows/http3-linux.yml +++ b/.github/workflows/http3-linux.yml @@ -30,8 +30,7 @@ name: 'Linux HTTP/3' - 'projects/**' concurrency: - # Hardcoded workflow filename as workflow name above is just Linux again - group: http3-${{ github.event.pull_request.number || github.sha }} + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} cancel-in-progress: true permissions: {} @@ -39,24 +38,27 @@ permissions: {} env: MAKEFLAGS: -j 5 CURL_CI: github + CURL_TEST_MIN: 1600 # handled in renovate.json OPENSSL_VERSION: 3.6.0 # renovate: datasource=github-tags depName=libressl/portable versioning=semver registryUrl=https://github.com - LIBRESSL_VERSION: 4.2.0 + LIBRESSL_VERSION: 4.2.1 # renovate: datasource=github-tags depName=awslabs/aws-lc versioning=semver registryUrl=https://github.com - AWSLC_VERSION: 1.61.4 + AWSLC_VERSION: 1.65.1 # renovate: datasource=github-tags depName=google/boringssl versioning=semver registryUrl=https://github.com - BORINGSSL_VERSION: 0.20251002.0 - # renovate: datasource=github-tags depName=gnutls/gnutls versioning=semver registryUrl=https://github.com - GNUTLS_VERSION: 3.8.10 + BORINGSSL_VERSION: 0.20251124.0 + # renovate: datasource=github-tags depName=gnutls/nettle versioning=semver registryUrl=https://github.com + NETTLE_VERSION: 3.10.2 + # renovate: datasource=github-tags depName=gnutls/gnutls versioning=semver extractVersion=^nettle_?(?.+)_release_.+$ registryUrl=https://github.com + GNUTLS_VERSION: 3.8.11 # renovate: datasource=github-tags depName=wolfSSL/wolfssl versioning=semver extractVersion=^v?(?.+)-stable$ registryUrl=https://github.com - WOLFSSL_VERSION: 5.8.2 + WOLFSSL_VERSION: 5.8.4 # renovate: datasource=github-tags depName=ngtcp2/nghttp3 versioning=semver registryUrl=https://github.com - NGHTTP3_VERSION: 1.12.0 + NGHTTP3_VERSION: 1.13.1 # renovate: datasource=github-tags depName=ngtcp2/ngtcp2 versioning=semver registryUrl=https://github.com - NGTCP2_VERSION: 1.16.0 + NGTCP2_VERSION: 1.18.0 # renovate: datasource=github-tags depName=nghttp2/nghttp2 versioning=semver registryUrl=https://github.com - NGHTTP2_VERSION: 1.67.1 + NGHTTP2_VERSION: 1.68.0 # renovate: datasource=github-tags depName=cloudflare/quiche versioning=semver registryUrl=https://github.com QUICHE_VERSION: 0.24.6 @@ -67,7 +69,7 @@ jobs: steps: - name: 'cache openssl' - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-openssl-http3-no-deprecated env: cache-name: cache-openssl-http3-no-deprecated @@ -76,7 +78,7 @@ jobs: key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.OPENSSL_VERSION }} - name: 'cache libressl' - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-libressl env: cache-name: cache-libressl @@ -85,7 +87,7 @@ jobs: key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.LIBRESSL_VERSION }} - name: 'cache awslc' - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-awslc env: cache-name: cache-awslc @@ -94,7 +96,7 @@ jobs: key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.AWSLC_VERSION }} - name: 'cache boringssl' - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-boringssl env: cache-name: cache-boringssl @@ -102,17 +104,26 @@ jobs: path: ~/boringssl/build key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.BORINGSSL_VERSION }} + - name: 'cache nettle' + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 + id: cache-nettle + env: + cache-name: cache-nettle + with: + path: ~/nettle/build + key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.NETTLE_VERSION }} + - name: 'cache gnutls' - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-gnutls env: cache-name: cache-gnutls with: path: ~/gnutls/build - key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.GNUTLS_VERSION }} + key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.GNUTLS_VERSION }}-${{ env.NETTLE_VERSION }} - name: 'cache wolfssl' - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-wolfssl env: cache-name: cache-wolfssl @@ -121,7 +132,7 @@ jobs: key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.WOLFSSL_VERSION }} - name: 'cache nghttp3' - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-nghttp3 env: cache-name: cache-nghttp3 @@ -130,16 +141,16 @@ jobs: key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.NGHTTP3_VERSION }} - name: 'cache ngtcp2' - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-ngtcp2 env: cache-name: cache-ngtcp2 with: path: ~/ngtcp2/build - key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.NGTCP2_VERSION }}-${{ env.OPENSSL_VERSION }}-${{ env.LIBRESSL_VERSION }}-${{ env.AWSLC_VERSION }}-${{ env.GNUTLS_VERSION }}-${{ env.WOLFSSL_VERSION }} + key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.NGTCP2_VERSION }}-${{ env.OPENSSL_VERSION }}-${{ env.LIBRESSL_VERSION }}-${{ env.AWSLC_VERSION }}-${{ env.NETTLE_VERSION }}-${{ env.GNUTLS_VERSION }}-${{ env.WOLFSSL_VERSION }} - name: 'cache ngtcp2 boringssl' - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-ngtcp2-boringssl env: cache-name: cache-ngtcp2-boringssl @@ -148,7 +159,7 @@ jobs: key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.NGTCP2_VERSION }}-${{ env.BORINGSSL_VERSION }} - name: 'cache nghttp2' - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-nghttp2 env: cache-name: cache-nghttp2 @@ -162,6 +173,7 @@ jobs: steps.cache-libressl.outputs.cache-hit != 'true' || steps.cache-awslc.outputs.cache-hit != 'true' || steps.cache-boringssl.outputs.cache-hit != 'true' || + steps.cache-nettle.outputs.cache-hit != 'true' || steps.cache-gnutls.outputs.cache-hit != 'true' || steps.cache-wolfssl.outputs.cache-hit != 'true' || steps.cache-nghttp3.outputs.cache-hit != 'true' || @@ -182,7 +194,7 @@ jobs: libbrotli-dev libzstd-dev zlib1g-dev \ libev-dev \ libc-ares-dev \ - nettle-dev libp11-kit-dev autopoint bison gperf gtk-doc-tools libtasn1-bin # for GnuTLS + libp11-kit-dev autopoint bison gperf gtk-doc-tools libtasn1-bin # for GnuTLS echo 'CC=gcc-12' >> "$GITHUB_ENV" echo 'CXX=g++-12' >> "$GITHUB_ENV" @@ -190,7 +202,7 @@ jobs: if: ${{ steps.cache-openssl-http3-no-deprecated.outputs.cache-hit != 'true' }} run: | cd ~ - git clone --quiet --depth=1 -b "openssl-${OPENSSL_VERSION}" https://github.com/openssl/openssl + git clone --quiet --depth 1 -b "openssl-${OPENSSL_VERSION}" https://github.com/openssl/openssl cd openssl ./config --prefix="$PWD"/build --libdir=lib no-makedepend no-apps no-docs no-tests no-deprecated make @@ -229,26 +241,37 @@ jobs: cmake --build . cmake --install . + - name: 'build nettle' + if: ${{ steps.cache-nettle.outputs.cache-hit != 'true' }} + run: | + cd ~ + curl --disable --fail --silent --show-error --connect-timeout 15 --max-time 120 --retry 6 --retry-connrefused \ + --location "https://ftpmirror.gnu.org/nettle/nettle-${NETTLE_VERSION}.tar.gz" | tar -xz + cd "nettle-${NETTLE_VERSION}" + ./configure --disable-dependency-tracking --prefix=/home/runner/nettle/build \ + --disable-silent-rules --disable-static --disable-openssl --disable-documentation + make install + - name: 'build gnutls' if: ${{ steps.cache-gnutls.outputs.cache-hit != 'true' }} run: | cd ~ - git clone --quiet --depth=1 -b "${GNUTLS_VERSION}" https://github.com/gnutls/gnutls.git - cd gnutls - # required: nettle-dev libp11-kit-dev libev-dev autopoint bison gperf gtk-doc-tools libtasn1-bin - ./bootstrap - ./configure --disable-dependency-tracking --prefix="$PWD"/build \ - LDFLAGS="-Wl,-rpath,$PWD/build/lib -L$PWD/build/lib" \ + curl --disable --fail --silent --show-error --connect-timeout 15 --max-time 120 --retry 6 --retry-connrefused \ + "https://www.gnupg.org/ftp/gcrypt/gnutls/v${GNUTLS_VERSION%.*}/gnutls-${GNUTLS_VERSION}.tar.xz" | tar -xJ + cd "gnutls-${GNUTLS_VERSION}" + # required: libp11-kit-dev libev-dev autopoint bison gperf gtk-doc-tools libtasn1-bin + ./configure --disable-dependency-tracking --prefix=/home/runner/gnutls/build \ + PKG_CONFIG_PATH=/home/runner/nettle/build/lib64/pkgconfig \ + LDFLAGS=-Wl,-rpath,/home/runner/nettle/build/lib64 \ --with-included-libtasn1 --with-included-unistring \ --disable-guile --disable-doc --disable-tests --disable-tools - make make install - name: 'build wolfssl' if: ${{ steps.cache-wolfssl.outputs.cache-hit != 'true' }} run: | cd ~ - git clone --quiet --depth=1 -b "v${WOLFSSL_VERSION}-stable" https://github.com/wolfSSL/wolfssl.git + git clone --quiet --depth 1 -b "v${WOLFSSL_VERSION}-stable" https://github.com/wolfSSL/wolfssl cd wolfssl ./autogen.sh ./configure --disable-dependency-tracking --enable-all --enable-quic \ @@ -260,9 +283,9 @@ jobs: if: ${{ steps.cache-nghttp3.outputs.cache-hit != 'true' }} run: | cd ~ - git clone --quiet --depth=1 -b "v${NGHTTP3_VERSION}" https://github.com/ngtcp2/nghttp3 + git clone --quiet --depth 1 -b "v${NGHTTP3_VERSION}" https://github.com/ngtcp2/nghttp3 cd nghttp3 - git submodule update --init --depth=1 + git submodule update --init --depth 1 autoreconf -fi ./configure --disable-dependency-tracking --prefix="$PWD"/build --enable-lib-only make @@ -273,7 +296,7 @@ jobs: # building twice to get crypto libs for ossl, libressl and awslc installed run: | cd ~ - git clone --quiet --depth=1 -b "v${NGTCP2_VERSION}" https://github.com/ngtcp2/ngtcp2 + git clone --quiet --depth 1 -b "v${NGTCP2_VERSION}" https://github.com/ngtcp2/ngtcp2 cd ngtcp2 autoreconf -fi ./configure --disable-dependency-tracking --prefix="$PWD"/build \ @@ -281,7 +304,7 @@ jobs: make install make clean ./configure --disable-dependency-tracking --prefix="$PWD"/build \ - PKG_CONFIG_PATH=/home/runner/openssl/build/lib/pkgconfig:/home/runner/gnutls/build/lib/pkgconfig:/home/runner/wolfssl/build/lib/pkgconfig \ + PKG_CONFIG_PATH=/home/runner/openssl/build/lib/pkgconfig:/home/runner/nettle/build/lib64/pkgconfig:/home/runner/gnutls/build/lib/pkgconfig:/home/runner/wolfssl/build/lib/pkgconfig \ --enable-lib-only --with-openssl --with-gnutls --with-wolfssl --with-boringssl \ BORINGSSL_LIBS='-L/home/runner/awslc/build/lib -lssl -lcrypto' \ BORINGSSL_CFLAGS='-I/home/runner/awslc/build/include' @@ -291,7 +314,7 @@ jobs: if: ${{ steps.cache-ngtcp2-boringssl.outputs.cache-hit != 'true' }} run: | cd ~ - git clone --quiet --depth=1 -b "v${NGTCP2_VERSION}" https://github.com/ngtcp2/ngtcp2 ngtcp2-boringssl + git clone --quiet --depth 1 -b "v${NGTCP2_VERSION}" https://github.com/ngtcp2/ngtcp2 ngtcp2-boringssl cd ngtcp2-boringssl autoreconf -fi ./configure --disable-dependency-tracking --prefix="$PWD"/build \ @@ -304,9 +327,9 @@ jobs: if: ${{ steps.cache-nghttp2.outputs.cache-hit != 'true' }} run: | cd ~ - git clone --quiet --depth=1 -b "v${NGHTTP2_VERSION}" https://github.com/nghttp2/nghttp2 + git clone --quiet --depth 1 -b "v${NGHTTP2_VERSION}" https://github.com/nghttp2/nghttp2 cd nghttp2 - git submodule update --init --depth=1 + git submodule update --init --depth 1 autoreconf -fi # required (for nghttpx application): libc-ares-dev libev-dev zlib1g-dev # optional (for nghttpx application): libbrotli-dev @@ -332,10 +355,10 @@ jobs: build: - name: 'openssl' PKG_CONFIG_PATH: /home/runner/openssl/build/lib/pkgconfig:/home/runner/nghttp3/build/lib/pkgconfig:/home/runner/ngtcp2/build/lib/pkgconfig:/home/runner/nghttp2/build/lib/pkgconfig + tflags: '--min=1640' configure: >- LDFLAGS=-Wl,-rpath,/home/runner/openssl/build/lib - --with-ngtcp2 --disable-ntlm - --with-openssl=/home/runner/openssl/build --enable-ssls-export + --with-openssl=/home/runner/openssl/build --with-ngtcp2 --enable-ssls-export - name: 'openssl' install_steps: skipall @@ -343,7 +366,6 @@ jobs: generate: >- -DOPENSSL_ROOT_DIR=/home/runner/openssl/build -DUSE_NGTCP2=ON -DCURL_DISABLE_LDAP=ON - -DCURL_DISABLE_NTLM=ON -DCMAKE_UNITY_BUILD=ON - name: 'libressl' @@ -351,29 +373,27 @@ jobs: PKG_CONFIG_PATH: /home/runner/libressl/build/lib/pkgconfig:/home/runner/nghttp3/build/lib/pkgconfig:/home/runner/ngtcp2/build/lib/pkgconfig:/home/runner/nghttp2/build/lib/pkgconfig configure: >- LDFLAGS=-Wl,-rpath,/home/runner/libressl/build/lib - --with-ngtcp2 --disable-ntlm - --with-openssl=/home/runner/libressl/build --enable-ssls-export + --with-openssl=/home/runner/libressl/build --with-ngtcp2 --enable-ssls-export --enable-unity - name: 'libressl' PKG_CONFIG_PATH: /home/runner/libressl/build/lib/pkgconfig:/home/runner/nghttp3/build/lib/pkgconfig:/home/runner/ngtcp2/build/lib/pkgconfig:/home/runner/nghttp2/build/lib/pkgconfig + tflags: '--min=1790' generate: >- - -DOPENSSL_ROOT_DIR=/home/runner/libressl/build - -DUSE_NGTCP2=ON -DCURL_DISABLE_NTLM=ON + -DOPENSSL_ROOT_DIR=/home/runner/libressl/build -DUSE_NGTCP2=ON - name: 'awslc' install_steps: skipall PKG_CONFIG_PATH: /home/runner/awslc/build/lib/pkgconfig:/home/runner/nghttp3/build/lib/pkgconfig:/home/runner/ngtcp2/build/lib/pkgconfig:/home/runner/nghttp2/build/lib/pkgconfig configure: >- LDFLAGS=-Wl,-rpath,/home/runner/awslc/build/lib - --with-ngtcp2 --disable-ntlm - --with-openssl=/home/runner/awslc/build --enable-ssls-export + --with-openssl=/home/runner/awslc/build --with-ngtcp2 --enable-ssls-export - name: 'awslc' PKG_CONFIG_PATH: /home/runner/awslc/build/lib/pkgconfig:/home/runner/nghttp3/build/lib/pkgconfig:/home/runner/ngtcp2/build/lib/pkgconfig:/home/runner/nghttp2/build/lib/pkgconfig + tflags: '--min=1790' generate: >- - -DOPENSSL_ROOT_DIR=/home/runner/awslc/build -DBUILD_SHARED_LIBS=OFF - -DUSE_NGTCP2=ON -DCURL_DISABLE_NTLM=ON + -DOPENSSL_ROOT_DIR=/home/runner/awslc/build -DUSE_NGTCP2=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_UNITY_BUILD=ON - name: 'boringssl' @@ -381,45 +401,45 @@ jobs: PKG_CONFIG_PATH: /home/runner/boringssl/build/lib/pkgconfig:/home/runner/nghttp3/build/lib/pkgconfig:/home/runner/ngtcp2-boringssl/build/lib/pkgconfig:/home/runner/nghttp2/build/lib/pkgconfig configure: >- LDFLAGS=-Wl,-rpath,/home/runner/boringssl/build/lib - --with-ngtcp2 --disable-ntlm - --with-openssl=/home/runner/boringssl/build --enable-ssls-export + --with-openssl=/home/runner/boringssl/build --with-ngtcp2 --enable-ssls-export - name: 'boringssl' PKG_CONFIG_PATH: /home/runner/boringssl/build/lib/pkgconfig:/home/runner/nghttp3/build/lib/pkgconfig:/home/runner/ngtcp2-boringssl/build/lib/pkgconfig:/home/runner/nghttp2/build/lib/pkgconfig + tflags: '--min=1790' generate: >- - -DOPENSSL_ROOT_DIR=/home/runner/boringssl/build -DBUILD_SHARED_LIBS=OFF - -DUSE_NGTCP2=ON -DCURL_DISABLE_NTLM=ON + -DOPENSSL_ROOT_DIR=/home/runner/boringssl/build -DUSE_NGTCP2=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_UNITY_BUILD=ON - name: 'gnutls' - install_packages: nettle-dev libp11-kit-dev + install_packages: libp11-kit-dev libssh-dev install_steps: skipall - PKG_CONFIG_PATH: /home/runner/gnutls/build/lib/pkgconfig:/home/runner/nghttp3/build/lib/pkgconfig:/home/runner/ngtcp2/build/lib/pkgconfig:/home/runner/nghttp2/build/lib/pkgconfig + PKG_CONFIG_PATH: /home/runner/nettle/build/lib64/pkgconfig:/home/runner/gnutls/build/lib/pkgconfig:/home/runner/nghttp3/build/lib/pkgconfig:/home/runner/ngtcp2/build/lib/pkgconfig:/home/runner/nghttp2/build/lib/pkgconfig + LDFLAGS: -Wl,-rpath,/home/runner/gnutls/build/lib -Wl,-rpath,/home/runner/nettle/build/lib64 -Wl,-rpath,/home/runner/ngtcp2/build/lib configure: >- - LDFLAGS=-Wl,-rpath,/home/runner/gnutls/build/lib - --with-ngtcp2 - --with-gnutls=/home/runner/gnutls/build --enable-ssls-export + --with-gnutls=/home/runner/gnutls/build --with-ngtcp2 --with-libssh --enable-ssls-export - name: 'gnutls' - install_packages: nettle-dev libp11-kit-dev - PKG_CONFIG_PATH: /home/runner/gnutls/build/lib/pkgconfig:/home/runner/nghttp3/build/lib/pkgconfig:/home/runner/ngtcp2/build/lib/pkgconfig:/home/runner/nghttp2/build/lib/pkgconfig + install_packages: libp11-kit-dev libssh-dev + PKG_CONFIG_PATH: /home/runner/nettle/build/lib64/pkgconfig:/home/runner/gnutls/build/lib/pkgconfig:/home/runner/nghttp3/build/lib/pkgconfig:/home/runner/ngtcp2/build/lib/pkgconfig:/home/runner/nghttp2/build/lib/pkgconfig + LDFLAGS: -Wl,-rpath,/home/runner/gnutls/build/lib + tflags: '--min=1840' generate: >- - -DCURL_USE_GNUTLS=ON - -DUSE_NGTCP2=ON -DCURL_DISABLE_NTLM=ON + -DCURL_USE_GNUTLS=ON -DUSE_NGTCP2=ON -DCURL_USE_LIBSSH=ON -DCMAKE_UNITY_BUILD=ON - name: 'wolfssl' + install_packages: libssh2-1-dev install_steps: skipall PKG_CONFIG_PATH: /home/runner/wolfssl/build/lib/pkgconfig:/home/runner/nghttp3/build/lib/pkgconfig:/home/runner/ngtcp2/build/lib/pkgconfig:/home/runner/nghttp2/build/lib/pkgconfig configure: >- LDFLAGS=-Wl,-rpath,/home/runner/wolfssl/build/lib - --with-ngtcp2 - --with-wolfssl=/home/runner/wolfssl/build - --enable-ech --enable-ssls-export + --with-wolfssl=/home/runner/wolfssl/build --with-ngtcp2 --enable-ech --with-libssh2 --enable-ssls-export --enable-unity - name: 'wolfssl' + install_packages: libssh2-1-dev PKG_CONFIG_PATH: /home/runner/wolfssl/build/lib/pkgconfig:/home/runner/nghttp3/build/lib/pkgconfig:/home/runner/ngtcp2/build/lib/pkgconfig:/home/runner/nghttp2/build/lib/pkgconfig + tflags: '--min=1840' generate: >- -DCURL_USE_WOLFSSL=ON -DUSE_NGTCP2=ON -DUSE_ECH=ON @@ -427,9 +447,9 @@ jobs: - name: 'openssl-quic' install_steps: skipall PKG_CONFIG_PATH: /home/runner/openssl/build/lib/pkgconfig:/home/runner/nghttp3/build/lib/pkgconfig:/home/runner/nghttp2/build/lib/pkgconfig + tflags: '--min=1640' configure: >- LDFLAGS=-Wl,-rpath,/home/runner/openssl/build/lib - --disable-ntlm --with-openssl=/home/runner/openssl/build --with-openssl-quic - name: 'openssl-quic' @@ -437,7 +457,6 @@ jobs: generate: >- -DOPENSSL_ROOT_DIR=/home/runner/openssl/build -DUSE_OPENSSL_QUIC=ON -DCURL_DISABLE_LDAP=ON - -DCURL_DISABLE_NTLM=ON -DCMAKE_UNITY_BUILD=ON - name: 'quiche' @@ -452,6 +471,7 @@ jobs: - name: 'quiche' PKG_CONFIG_PATH: /home/runner/nghttp2/build/lib/pkgconfig:/home/runner/quiche/target/release + tflags: '--min=1790' generate: >- -DOPENSSL_ROOT_DIR=/home/runner/quiche/quiche/deps/boringssl/src -DUSE_QUICHE=ON @@ -470,15 +490,14 @@ jobs: sudo rm -f /var/lib/man-db/auto-update sudo apt-get -o Dpkg::Use-Pty=0 install \ libtool autoconf automake pkgconf \ - libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev libidn2-0-dev libldap-dev libuv1-dev \ + libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev libidn2-0-dev libldap-dev libuv1-dev valgrind \ ${INSTALL_PACKAGES} \ ${MATRIX_INSTALL_PACKAGES} echo 'CC=gcc-12' >> "$GITHUB_ENV" echo 'CXX=g++-12' >> "$GITHUB_ENV" - name: 'cache openssl' - if: ${{ matrix.build.name == 'openssl' || matrix.build.name == 'openssl-quic' }} - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-openssl-http3-no-deprecated env: cache-name: cache-openssl-http3-no-deprecated @@ -488,7 +507,7 @@ jobs: fail-on-cache-miss: true - name: 'cache libressl' - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-libressl env: cache-name: cache-libressl @@ -498,7 +517,7 @@ jobs: fail-on-cache-miss: true - name: 'cache awslc' - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-awslc env: cache-name: cache-awslc @@ -508,7 +527,7 @@ jobs: fail-on-cache-miss: true - name: 'cache boringssl' - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-boringssl env: cache-name: cache-boringssl @@ -517,20 +536,31 @@ jobs: key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.BORINGSSL_VERSION }} fail-on-cache-miss: true + - name: 'cache nettle' + if: ${{ matrix.build.name == 'gnutls' }} + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 + id: cache-nettle + env: + cache-name: cache-nettle + with: + path: ~/nettle/build + key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.NETTLE_VERSION }} + fail-on-cache-miss: true + - name: 'cache gnutls' if: ${{ matrix.build.name == 'gnutls' }} - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-gnutls env: cache-name: cache-gnutls with: path: ~/gnutls/build - key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.GNUTLS_VERSION }} + key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.GNUTLS_VERSION }}-${{ env.NETTLE_VERSION }} fail-on-cache-miss: true - name: 'cache wolfssl' if: ${{ matrix.build.name == 'wolfssl' }} - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-wolfssl env: cache-name: cache-wolfssl @@ -540,7 +570,7 @@ jobs: fail-on-cache-miss: true - name: 'cache nghttp3' - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-nghttp3 env: cache-name: cache-nghttp3 @@ -550,17 +580,17 @@ jobs: fail-on-cache-miss: true - name: 'cache ngtcp2' - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-ngtcp2 env: cache-name: cache-ngtcp2 with: path: ~/ngtcp2/build - key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.NGTCP2_VERSION }}-${{ env.OPENSSL_VERSION }}-${{ env.LIBRESSL_VERSION }}-${{ env.AWSLC_VERSION }}-${{ env.GNUTLS_VERSION }}-${{ env.WOLFSSL_VERSION }} + key: ${{ runner.os }}-http3-build-${{ env.cache-name }}-${{ env.NGTCP2_VERSION }}-${{ env.OPENSSL_VERSION }}-${{ env.LIBRESSL_VERSION }}-${{ env.AWSLC_VERSION }}-${{ env.NETTLE_VERSION }}-${{ env.GNUTLS_VERSION }}-${{ env.WOLFSSL_VERSION }} fail-on-cache-miss: true - name: 'cache ngtcp2 boringssl' - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-ngtcp2-boringssl env: cache-name: cache-ngtcp2-boringssl @@ -570,7 +600,7 @@ jobs: fail-on-cache-miss: true - name: 'cache nghttp2' - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-nghttp2 env: cache-name: cache-nghttp2 @@ -581,7 +611,7 @@ jobs: - name: 'cache quiche' if: ${{ matrix.build.name == 'quiche' }} - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-quiche env: cache-name: cache-quiche @@ -593,7 +623,7 @@ jobs: if: ${{ matrix.build.name == 'quiche' && steps.cache-quiche.outputs.cache-hit != 'true' }} run: | cd ~ - git clone --quiet --depth=1 -b "${QUICHE_VERSION}" --recursive https://github.com/cloudflare/quiche.git + git clone --quiet --depth 1 -b "${QUICHE_VERSION}" --recursive https://github.com/cloudflare/quiche cd quiche #### Work-around https://github.com/curl/curl/issues/7927 ####### #### See https://github.com/alexcrichton/cmake-rs/issues/131 #### @@ -602,15 +632,14 @@ jobs: cargo build -v --package quiche --release --features ffi,pkg-config-meta,qlog --verbose ln -s libquiche.so target/release/libquiche.so.0 mkdir -v quiche/deps/boringssl/src/lib - # shellcheck disable=SC2046 - ln -vnf $(find target/release -name libcrypto.a -o -name libssl.a) quiche/deps/boringssl/src/lib/ + find target/release \( -name libcrypto.a -o -name libssl.a \) -exec ln -vnf -- '{}' 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 - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false @@ -620,6 +649,7 @@ jobs: - name: 'configure' env: + LDFLAGS: '${{ matrix.build.LDFLAGS }}' MATRIX_CONFIGURE: '${{ matrix.build.configure }}' MATRIX_GENERATE: '${{ matrix.build.generate }}' MATRIX_PKG_CONFIG_PATH: '${{ matrix.build.PKG_CONFIG_PATH }}' @@ -684,6 +714,18 @@ jobs: env: TFLAGS: '${{ matrix.build.tflags }}' run: | + TFLAGS+=' -n' + source ~/venv/bin/activate + if [ "${MATRIX_BUILD}" = 'cmake' ]; then + cmake --build bld --verbose --target test-ci + else + make -C bld V=1 test-ci + fi + + - name: 'run tests (valgrind)' + if: ${{ !contains(matrix.build.install_steps, 'skipall') && !contains(matrix.build.install_steps, 'skiprun') }} + run: | + export TFLAGS='-j6 --min=4 HTTP/3' source ~/venv/bin/activate if [ "${MATRIX_BUILD}" = 'cmake' ]; then cmake --build bld --verbose --target test-ci @@ -697,7 +739,7 @@ jobs: [ -d ~/venv ] || python3 -m venv ~/venv ~/venv/bin/pip --disable-pip-version-check --no-input --no-cache-dir install --progress-bar off --prefer-binary -r tests/http/requirements.txt - - name: 'run pytest event based' + - name: 'run pytest (event based)' if: ${{ !contains(matrix.build.install_steps, 'skipall') && !contains(matrix.build.install_steps, 'skiprun') }} env: CURL_TEST_EVENT: 1 diff --git a/.github/workflows/label.yml b/.github/workflows/label.yml index a5f42f9d409b..0c169e607573 100644 --- a/.github/workflows/label.yml +++ b/.github/workflows/label.yml @@ -13,6 +13,10 @@ name: 'Labeler' 'on': [pull_request_target] # zizmor: ignore[dangerous-triggers] +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} + cancel-in-progress: true + permissions: {} jobs: diff --git a/.github/workflows/linux-old.yml b/.github/workflows/linux-old.yml index e145633708de..04e01d9083f0 100644 --- a/.github/workflows/linux-old.yml +++ b/.github/workflows/linux-old.yml @@ -11,12 +11,12 @@ # is still supported (as of this writing). # stretch has ELTS support from Freexian until 2027-06-30 # For ELTS info see https://www.freexian.com/lts/extended/docs/how-to-use-extended-lts/ -# The Debian key will expire 2025-05-20, after which package signature +# The Debian key expires 2025-05-20, after which package signature # verification may need to be disabled. # httrack is one of the smallest downloaders, needed to bootstrap ELTS, -# and won't conflict with the curl we're building. +# and doesn not conflict with the curl we are building. -name: 'Old Linux' +name: 'Linux Old' 'on': push: @@ -43,19 +43,26 @@ name: 'Old Linux' - 'plan9/**' - 'projects/**' +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} + cancel-in-progress: true + permissions: {} env: MAKEFLAGS: -j 5 CURL_CI: github + CURL_TEST_MIN: 1500 DEBIAN_FRONTEND: noninteractive jobs: cmake-autotools: - name: 'cmake & autotools' + name: 'autotools & cmake' runs-on: 'ubuntu-latest' container: 'debian:stretch' + env: + CMAKE_VERSION: '3.7.0' # Earliest version supported by curl steps: - name: 'install prereqs' # Remember, this shell is dash, not bash @@ -68,105 +75,114 @@ jobs: dpkg -i freexian-archive-keyring_2022.06.08_all.deb echo 'deb http://deb.freexian.com/extended-lts stretch-lts main contrib non-free' | tee /etc/apt/sources.list.d/extended-lts.list apt-get -o Dpkg::Use-Pty=0 update - apt-get -o Dpkg::Use-Pty=0 install -y --no-install-suggests --no-install-recommends cmake make automake autoconf libtool gcc pkg-config libpsl-dev libzstd-dev zlib1g-dev libgnutls28-dev libc-ares-dev libkrb5-dev libldap2-dev librtmp-dev stunnel4 groff + apt-get -o Dpkg::Use-Pty=0 install -y --no-install-suggests --no-install-recommends make automake autoconf libtool gcc pkg-config libpsl-dev libzstd-dev zlib1g-dev libc-ares-dev libkrb5-dev libldap2-dev librtmp-dev stunnel4 # GitHub's actions/checkout needs newer glibc and libstdc++. The latter also depends on - # gcc-8-base, but it doesn't actually seem used in our situation and isn't available in + # gcc-8-base, but it does not actually seem used in our situation and is not available in # the main repo, so force the install. httrack --get https://deb.freexian.com/extended-lts/pool/main/g/glibc/libc6_2.28-10+deb10u5_amd64.deb httrack --get https://deb.freexian.com/extended-lts/pool/main/g/gcc-8/libstdc++6_8.3.0-6_amd64.deb dpkg -i --force-depends libc6_*_amd64.deb libstdc++6_*_amd64.deb - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - name: 'install prereqs (cmake)' + run: | + cd ~ + fn="cmake-${CMAKE_VERSION}-linux-x86_64" + httrack --get "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/${fn}.tar.gz" + tar -xf "${fn}".tar*.gz + rm -f "${fn}".tar*.gz + mv "cmake-${CMAKE_VERSION}-Linux-x86_64" cmake + + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - - name: 'cmake build-only configure (out-of-tree)' + - name: 'CM build-only configure (out-of-tree)' run: | mkdir bld-1 cd bld-1 - cmake .. -DCMAKE_UNITY_BUILD=ON -DCURL_WERROR=ON -DBUILD_SHARED_LIBS=ON \ - -DCURL_USE_GNUTLS=ON -DENABLE_ARES=OFF -DCURL_ZSTD=OFF -DCURL_USE_GSSAPI=OFF -DCURL_USE_LIBSSH2=OFF -DCURL_USE_LIBSSH=OFF -DUSE_LIBRTMP=ON + "$HOME"/cmake/bin/cmake .. -DCMAKE_UNITY_BUILD=ON -DCURL_WERROR=ON -DBUILD_SHARED_LIBS=ON \ + -DCURL_ENABLE_SSL=OFF -DENABLE_ARES=OFF -DCURL_ZSTD=OFF -DCURL_USE_GSSAPI=OFF -DCURL_USE_LIBSSH2=OFF -DCURL_USE_LIBSSH=OFF -DUSE_LIBRTMP=ON - - name: 'cmake build-only build' + - name: 'CM build-only build' run: VERBOSE=1 make -C bld-1 install - - name: 'cmake build-only curl -V' + - name: 'CM build-only curl -V' run: bld-1/src/curl --disable --version - - name: 'cmake build-only configure log' + - name: 'CM build-only configure log' if: ${{ !cancelled() }} run: cat bld-1/CMakeFiles/CMake*.log 2>/dev/null || true - - name: 'cmake build-only curl_config.h' + - name: 'CM build-only curl_config.h' run: | echo '::group::raw'; cat bld-1/lib/curl_config.h || true; echo '::endgroup::' grep -F '#define' bld-1/lib/curl_config.h | sort || true # when this job can get a libssh version 0.9.0 or later, this should get # that enabled again - - name: 'cmake configure (out-of-tree, c-ares, zstd, gssapi)' + - name: 'CM configure (out-of-tree, c-ares, zstd, gssapi)' run: | mkdir bld-cares cd bld-cares - cmake .. -DCMAKE_UNITY_BUILD=ON -DCURL_WERROR=ON -DBUILD_SHARED_LIBS=ON \ - -DCURL_USE_GNUTLS=ON -DENABLE_ARES=ON -DCURL_USE_GSSAPI=ON -DCURL_USE_LIBSSH2=OFF -DCURL_USE_LIBSSH=OFF -DUSE_LIBRTMP=ON \ + "$HOME"/cmake/bin/cmake .. -DCMAKE_UNITY_BUILD=ON -DCURL_WERROR=ON -DBUILD_SHARED_LIBS=ON \ + -DCURL_ENABLE_SSL=OFF -DENABLE_ARES=ON -DCURL_USE_GSSAPI=ON -DCURL_USE_LIBSSH2=OFF -DCURL_USE_LIBSSH=OFF -DUSE_LIBRTMP=ON \ -DCURL_LIBCURL_VERSIONED_SYMBOLS=ON - - name: 'cmake configure log' + - name: 'CM configure log' if: ${{ !cancelled() }} run: cat bld-cares/CMakeFiles/CMake*.log 2>/dev/null || true - - name: 'cmake curl_config.h' + - name: 'CM curl_config.h' run: | echo '::group::raw'; cat bld-cares/lib/curl_config.h || true; echo '::endgroup::' grep -F '#define' bld-cares/lib/curl_config.h | sort || true - - name: 'cmake build' + - name: 'CM build' run: make -C bld-cares - - name: 'cmake curl -V' + - name: 'CM curl -V' run: bld-cares/src/curl --disable --version - - name: 'cmake install' + - name: 'CM install' run: make -C bld-cares install - - name: 'cmake build tests' + - name: 'CM build tests' run: make -C bld-cares testdeps - - name: 'cmake run tests' + - name: 'CM run tests' run: make -C bld-cares test-ci - - name: 'cmake build examples' + - name: 'CM build examples' run: make -C bld-cares curl-examples-build - - name: 'autoreconf' + - name: 'AM autoreconf' run: autoreconf -fi - - name: 'autotools configure (out-of-tree, c-ares, zstd, gssapi)' + - name: 'AM configure (out-of-tree, c-ares, zstd, gssapi)' run: | mkdir bld-am cd bld-am ../configure --disable-dependency-tracking --enable-unity --enable-warnings --enable-werror \ - --with-gnutls --enable-ares --without-libssh2 --with-zstd --with-gssapi --with-librtmp \ + --without-ssl --enable-ares --without-libssh2 --with-zstd --with-gssapi --with-librtmp \ --prefix="$PWD"/../curl-install-am - - name: 'autotools configure log' + - name: 'AM configure log' if: ${{ !cancelled() }} run: cat bld-am/config.log 2>/dev/null || true - - name: 'autotools curl_config.h' + - name: 'AM curl_config.h' run: | echo '::group::raw'; cat bld-am/lib/curl_config.h || true; echo '::endgroup::' grep -F '#define' bld-am/lib/curl_config.h | sort || true - - name: 'autotools build' + - name: 'AM build' run: make -C bld-am - - name: 'autotools curl -V' + - name: 'AM curl -V' run: bld-am/src/curl --disable --version - - name: 'autotools install' + - name: 'AM install' run: make -C bld-am install - - name: 'autotools build tests' + - name: 'AM build tests' run: make -C bld-am/tests all diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 2d674dc195cf..acd34565d3a3 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -36,30 +36,37 @@ permissions: {} env: MAKEFLAGS: -j 5 CURL_CI: github + CURL_TEST_MIN: 1600 CURL_CLANG_TIDYFLAGS: '-checks=-clang-analyzer-security.insecureAPI.bzero,-clang-analyzer-security.insecureAPI.strcpy,-clang-analyzer-optin.performance.Padding,-clang-analyzer-security.ArrayBound,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,-clang-analyzer-valist.Uninitialized' # renovate: datasource=github-tags depName=libressl/portable versioning=semver registryUrl=https://github.com - LIBRESSL_VERSION: 4.2.0 + LIBRESSL_VERSION: 4.2.1 # renovate: datasource=github-tags depName=wolfSSL/wolfssl versioning=semver extractVersion=^v?(?.+)-stable$ registryUrl=https://github.com - WOLFSSL_VERSION: 5.8.2 + WOLFSSL_VERSION: 5.8.4 # renovate: datasource=github-tags depName=Mbed-TLS/mbedtls versioning=semver registryUrl=https://github.com - MBEDTLS_VERSION: 3.6.4 + MBEDTLS_VERSION: 4.0.0 + # renovate: datasource=github-tags depName=Mbed-TLS/mbedtls versioning=semver:^3.0.0 registryUrl=https://github.com + MBEDTLS_VERSION_PREV: 3.6.4 # renovate: datasource=github-tags depName=awslabs/aws-lc versioning=semver registryUrl=https://github.com - AWSLC_VERSION: 1.61.4 + AWSLC_VERSION: 1.65.1 # renovate: datasource=github-tags depName=google/boringssl versioning=semver registryUrl=https://github.com - BORINGSSL_VERSION: 0.20251002.0 + BORINGSSL_VERSION: 0.20251124.0 # handled in renovate.json OPENSSL_VERSION: 3.6.0 # renovate: datasource=github-tags depName=rustls/rustls-ffi versioning=semver registryUrl=https://github.com RUSTLS_VERSION: 0.15.0 # handled in renovate.json OPENLDAP_VERSION: 2.6.10 + # renovate: datasource=github-tags depName=nghttp2/nghttp2 versioning=semver registryUrl=https://github.com + NGHTTP2_VERSION: 1.68.0 + # renovate: datasource=github-releases depName=pizlonator/fil-c versioning=semver-coerced registryUrl=https://github.com + FIL_C_VERSION: 0.677 jobs: linux: name: ${{ matrix.build.generate && 'CM' || 'AM' }} ${{ matrix.build.name }} runs-on: ${{ matrix.build.image || 'ubuntu-latest' }} container: ${{ matrix.build.container }} - timeout-minutes: 45 + timeout-minutes: 25 env: MATRIX_BUILD: ${{ matrix.build.generate && 'cmake' || 'autotools' }} MATRIX_INSTALL_PACKAGES: '${{ matrix.build.install_packages }}' @@ -105,14 +112,14 @@ jobs: -DCURL_USE_GSSAPI=ON - name: 'mbedtls clang' - install_packages: libnghttp2-dev libldap-dev clang + install_packages: libssh-dev libnghttp2-dev libldap-dev clang install_steps: mbedtls pytest - configure: CC=clang LDFLAGS=-Wl,-rpath,/home/runner/mbedtls/lib --with-mbedtls=/home/runner/mbedtls --enable-debug --with-fish-functions-dir --with-zsh-functions-dir + configure: CC=clang LDFLAGS=-Wl,-rpath,/home/runner/mbedtls/lib --with-mbedtls=/home/runner/mbedtls --with-libssh --enable-debug --with-fish-functions-dir --with-zsh-functions-dir - - name: 'mbedtls' - install_packages: libnghttp2-dev libuv1-dev - install_steps: mbedtls - PKG_CONFIG_PATH: /home/runner/mbedtls/lib/pkgconfig # Requires v3.6.0 + - name: 'mbedtls-prev' + install_packages: libssh2-1-dev libnghttp2-dev libuv1-dev + install_steps: mbedtls-prev pytest + PKG_CONFIG_PATH: /home/runner/mbedtls-prev/lib/pkgconfig # Requires v3.6.0 generate: -DCURL_USE_MBEDTLS=ON -DCURL_USE_LIBUV=ON -DENABLE_DEBUG=ON - name: 'mbedtls-pkg MultiSSL !pc' @@ -147,11 +154,12 @@ jobs: - name: 'openssl libssh2 sync-resolver valgrind' install_packages: libidn2-dev libssh2-1-dev libnghttp2-dev libldap-dev valgrind - generate: -DENABLE_DEBUG=ON -DENABLE_THREADED_RESOLVER=OFF -DCURL_USE_LIBSSH2=ON + generate: -DENABLE_DEBUG=ON -DENABLE_THREADED_RESOLVER=OFF - name: 'openssl' + install_packages: libssh-dev install_steps: pytest - configure: CFLAGS=-std=gnu89 --with-openssl --enable-debug + configure: CFLAGS=-std=gnu89 --with-openssl --with-libssh --enable-debug - name: 'openssl arm' install_steps: pytest @@ -169,8 +177,8 @@ jobs: configure: CC=clang --disable-shared --with-openssl --with-gssapi --enable-debug --disable-docs --disable-manual --with-ldap=/home/runner/openldap-static --with-ldap-lib=ldap --with-lber-lib=lber - name: 'openssl clang krb5 LTO' - install_packages: libkrb5-dev clang - install_steps: skiprun + install_packages: libssh2-1-dev libkrb5-dev clang + install_steps: skiprun pytest CC: clang generate: -DCURL_USE_OPENSSL=ON -DCURL_USE_GSSAPI=ON -DENABLE_DEBUG=ON -DCURL_LTO=ON @@ -178,6 +186,7 @@ jobs: configure: --with-openssl --disable-ipv6 --enable-debug --disable-unity --disable-libcurl-option --disable-digest-auth - name: 'openssl https-only' + tflags: '--min=1150' configure: >- --with-openssl --enable-debug --disable-unity --disable-dict --disable-gopher --disable-ldap --disable-telnet @@ -189,13 +198,13 @@ jobs: - name: 'openssl torture !FTP' install_packages: libnghttp2-dev libssh2-1-dev libc-ares-dev generate: -DCURL_USE_OPENSSL=ON -DENABLE_DEBUG=ON -DENABLE_ARES=ON - tflags: -t --shallow=25 !FTP + tflags: '-t --shallow=25 !FTP --min=1450' torture: true - name: 'openssl torture FTP' install_packages: libnghttp2-dev libssh2-1-dev libc-ares-dev generate: -DCURL_USE_OPENSSL=ON -DENABLE_DEBUG=ON -DENABLE_ARES=ON - tflags: -t --shallow=20 FTP + tflags: '-t --shallow=20 FTP --min=260' torture: true - name: 'openssl i686' @@ -209,8 +218,20 @@ jobs: --with-openssl --with-librtmp --with-libssh2 --with-libidn2 --enable-ares --enable-debug - name: '!ssl !http !smtp !imap' + tflags: '--min=475' configure: --without-ssl --enable-debug --disable-http --disable-smtp --disable-imap --disable-unity + - name: 'libressl Fil-C' + install_steps: filc libressl-filc nghttp2-filc pytest + tflags: '!776' # adds 1-9 minutes to the test run step, and fails consistently + CC: /home/runner/filc/build/bin/filcc + PKG_CONFIG_PATH: /home/runner/nghttp2/lib/pkgconfig + generate: >- + -DBUILD_STATIC_LIBS=ON -DBUILD_SHARED_LIBS=OFF -DCMAKE_UNITY_BUILD=OFF -DCURL_DISABLE_TYPECHECK=ON + -DOPENSSL_ROOT_DIR=/home/runner/libressl -DCURL_USE_LIBPSL=OFF + -DCURL_ZLIB=OFF -DCURL_BROTLI=OFF -DCURL_ZSTD=OFF + -DCURL_DISABLE_LDAP=ON -DUSE_LIBIDN2=OFF -DCURL_USE_LIBSSH2=OFF + - name: 'clang-tidy' install_packages: clang-tidy libssl-dev libidn2-dev libssh2-1-dev libnghttp2-dev libldap-dev libkrb5-dev librtmp-dev libgnutls28-dev install_steps: skipall mbedtls rustls wolfssl-opensslextra @@ -221,7 +242,7 @@ jobs: configure: >- --with-wolfssl=/home/runner/wolfssl-opensslextra --with-openssl --with-rustls --with-mbedtls=/home/runner/mbedtls --with-gnutls --with-libgsasl --with-librtmp --with-libssh2 --with-libidn2 - --enable-ech --with-gssapi --enable-ssls-export + --enable-ech --with-gssapi --enable-ssls-export --disable-typecheck - name: 'scan-build' install_packages: clang-tools clang libssl-dev libidn2-dev libssh2-1-dev libnghttp2-dev libldap-dev libgss-dev librtmp-dev libgnutls28-dev @@ -236,10 +257,10 @@ jobs: --with-wolfssl=/home/runner/wolfssl-opensslextra --with-openssl --with-rustls --with-mbedtls=/home/runner/mbedtls --with-gnutls --with-libgsasl --with-librtmp --with-libssh2 --with-libidn2 --enable-ech --with-gssapi --enable-ssls-export - --disable-debug --disable-unity + --disable-debug --disable-unity --disable-typecheck - name: 'scan-build H3 c-ares' - install_packages: clang-tools clang libidn2-dev libnghttp2-dev + install_packages: clang-tools clang libidn2-dev libssh-dev libnghttp2-dev install_steps: skipall install_steps_brew: openssl libngtcp2 libnghttp3 c-ares CC: clang @@ -249,8 +270,8 @@ jobs: PKG_CONFIG_PATH: /home/linuxbrew/.linuxbrew/opt/libngtcp2/lib/pkgconfig:/home/linuxbrew/.linuxbrew/opt/libnghttp3/lib/pkgconfig:/home/linuxbrew/.linuxbrew/opt/c-ares/lib/pkgconfig configure: >- --with-openssl=/home/linuxbrew/.linuxbrew/opt/openssl --with-ngtcp2 --with-nghttp3= - --with-libidn2 --enable-httpsrr --enable-ares - --disable-debug --disable-unity + --with-libidn2 --with-libssh --enable-httpsrr --enable-ares + --disable-debug --disable-unity --disable-typecheck --disable-verbose - name: 'address-sanitizer' @@ -264,10 +285,10 @@ jobs: - name: 'address-sanitizer H3 c-ares' install_packages: clang libubsan1 libasan8 libtsan2 install_steps: pytest - install_steps_brew: openssl libngtcp2 libnghttp3 c-ares + install_steps_brew: openssl libssh2 libngtcp2 libnghttp3 c-ares 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 -ldl -lubsan -Wl,-rpath,/home/linuxbrew/.linuxbrew/opt/c-ares/lib - PKG_CONFIG_PATH: /home/linuxbrew/.linuxbrew/opt/libngtcp2/lib/pkgconfig:/home/linuxbrew/.linuxbrew/opt/libnghttp3/lib/pkgconfig:/home/linuxbrew/.linuxbrew/opt/c-ares/lib/pkgconfig + PKG_CONFIG_PATH: /home/linuxbrew/.linuxbrew/opt/libssh2/lib/pkgconfig:/home/linuxbrew/.linuxbrew/opt/libngtcp2/lib/pkgconfig:/home/linuxbrew/.linuxbrew/opt/libnghttp3/lib/pkgconfig:/home/linuxbrew/.linuxbrew/opt/c-ares/lib/pkgconfig CC: clang generate: -DENABLE_DEBUG=ON -DCURL_USE_OPENSSL=ON -DOPENSSL_ROOT_DIR=/home/linuxbrew/.linuxbrew/opt/openssl -DUSE_NGTCP2=ON -DUSE_SSLS_EXPORT=ON -DENABLE_ARES=ON @@ -286,16 +307,17 @@ jobs: LDFLAGS: -fsanitize=memory LIBS: -ldl configure: CC=clang --without-ssl --without-zlib --without-brotli --without-zstd --without-libpsl --without-nghttp2 --enable-debug + tflags: '--min=1480' - name: 'event-based' install_packages: libssh-dev configure: --enable-debug --disable-shared --disable-threaded-resolver --with-libssh --with-openssl - tflags: -n --test-event '!TLS-SRP' + tflags: '-n --test-event --min=1350' - name: 'duphandle' install_packages: libssh-dev configure: --enable-debug --disable-shared --disable-threaded-resolver --with-libssh --with-openssl - tflags: -n --test-duphandle '!TLS-SRP' + tflags: '-n --test-duphandle' - name: 'rustls valgrind' install_packages: libnghttp2-dev libldap-dev valgrind @@ -312,10 +334,10 @@ jobs: install_steps: intel configure: CC=icc --enable-debug --with-openssl - - name: 'Slackware openssl gssapi gcc' - # These are essentially the same flags used to build the curl Slackware package + - name: 'Slackware !ssl gssapi gcc' + # Flags used to build the curl Slackware package, except OpenSSL 1.1.0: # https://ftpmirror.infania.net/slackware/slackware64-current/source/n/curl/curl.SlackBuild - configure: --enable-debug --with-openssl --with-libssh2 --with-gssapi --enable-ares --enable-static=no --without-ca-bundle --with-ca-path=/etc/ssl/certs + configure: --enable-debug --without-ssl --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' @@ -349,7 +371,7 @@ jobs: HOMEBREW_NO_AUTO_UPDATE=1 /home/linuxbrew/.linuxbrew/bin/brew install ${INSTALL_PACKAGES_BREW} fi - - name: 'install prereqs' + - name: 'install prereqs (i686)' if: ${{ contains(matrix.build.name, 'i686') }} run: | sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list @@ -361,7 +383,7 @@ jobs: libpsl-dev:i386 libbrotli-dev:i386 libzstd-dev:i386 \ ${MATRIX_INSTALL_PACKAGES} - - name: 'install dependencies' + - name: 'install prereqs (alpine)' if: ${{ startsWith(matrix.build.container, 'alpine') }} run: | apk add --no-cache build-base autoconf automake libtool perl openssl-dev \ @@ -370,9 +392,19 @@ jobs: py3-impacket py3-asn1 py3-six py3-pycryptodomex \ perl-time-hires openssh stunnel sudo git openssl + - name: 'install Fil-C' + if: ${{ contains(matrix.build.install_steps, 'filc') }} + run: | + cd /home/runner + curl --disable --fail --silent --show-error --connect-timeout 15 --max-time 120 --retry 6 --retry-connrefused \ + --location "https://github.com/pizlonator/fil-c/releases/download/v${FIL_C_VERSION}/filc-${FIL_C_VERSION}-linux-x86_64.tar.xz" | tar -xJ + mv "filc-${FIL_C_VERSION}-linux-x86_64" filc + cd filc + ./setup.sh + - name: 'cache libressl' if: ${{ contains(matrix.build.install_steps, 'libressl') }} - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-libressl env: cache-name: cache-libressl @@ -390,9 +422,52 @@ jobs: cmake --build . cmake --install . + - name: 'cache libressl (filc)' + if: ${{ contains(matrix.build.install_steps, 'libressl-filc') }} + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 + id: cache-libressl-filc + env: + cache-name: cache-libressl-filc + with: + path: ~/libressl + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.LIBRESSL_VERSION }}-${{ env.FIL_C_VERSION }} + + - name: 'build libressl (filc)' + if: ${{ contains(matrix.build.install_steps, 'libressl-filc') && steps.cache-libressl-filc.outputs.cache-hit != 'true' }} + run: | + curl --disable --fail --silent --show-error --connect-timeout 15 --max-time 120 --retry 6 --retry-connrefused \ + --location "https://github.com/libressl/portable/releases/download/v${LIBRESSL_VERSION}/libressl-${LIBRESSL_VERSION}.tar.gz" | tar -xz + cd "libressl-${LIBRESSL_VERSION}" + cmake -B . -G Ninja -DLIBRESSL_APPS=OFF -DLIBRESSL_TESTS=OFF -DCMAKE_INSTALL_PREFIX=/home/runner/libressl \ + -DCMAKE_C_COMPILER=/home/runner/filc/build/bin/filcc -DENABLE_ASM=OFF + cmake --build . + cmake --install . + + - name: 'cache nghttp2 (filc)' + if: ${{ contains(matrix.build.install_steps, 'nghttp2-filc') }} + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 + id: cache-nghttp2-filc + env: + cache-name: cache-nghttp2-filc + with: + path: ~/nghttp2 + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.NGHTTP2_VERSION }}-${{ env.FIL_C_VERSION }} + + - name: 'build nghttp2 (filc)' + if: ${{ contains(matrix.build.install_steps, 'nghttp2-filc') && steps.cache-nghttp2-filc.outputs.cache-hit != 'true' }} + run: | + curl --disable --fail --silent --show-error --connect-timeout 15 --max-time 120 --retry 6 --retry-connrefused \ + --location "https://github.com/nghttp2/nghttp2/releases/download/v${NGHTTP2_VERSION}/nghttp2-${NGHTTP2_VERSION}.tar.xz" | tar -xJ + cd "nghttp2-${NGHTTP2_VERSION}" + cmake -B . -G Ninja -DENABLE_LIB_ONLY=ON -DBUILD_TESTING=OFF -DENABLE_DOC=OFF -DCMAKE_INSTALL_PREFIX=/home/runner/nghttp2 \ + -DBUILD_STATIC_LIBS=ON -DBUILD_SHARED_LIBS=OFF \ + -DCMAKE_C_COMPILER=/home/runner/filc/build/bin/filcc + cmake --build . + cmake --install . + - name: 'cache wolfssl (all)' if: ${{ contains(matrix.build.install_steps, 'wolfssl-all') }} - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-wolfssl-all env: cache-name: cache-wolfssl-all @@ -413,7 +488,7 @@ jobs: - name: 'cache wolfssl (opensslextra)' # does support `OPENSSL_COEXIST` if: ${{ contains(matrix.build.install_steps, 'wolfssl-opensslextra') }} - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-wolfssl-opensslextra env: cache-name: cache-wolfssl-opensslextra @@ -434,8 +509,8 @@ jobs: - name: 'cache mbedtls' if: ${{ contains(matrix.build.install_steps, 'mbedtls') }} - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 - id: cache-mbedtls + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 + id: cache-mbedtls-threadsafe env: cache-name: cache-mbedtls-threadsafe with: @@ -443,7 +518,7 @@ jobs: key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.MBEDTLS_VERSION }} - name: 'build mbedtls' - if: ${{ contains(matrix.build.install_steps, 'mbedtls') && steps.cache-mbedtls.outputs.cache-hit != 'true' }} + if: ${{ contains(matrix.build.install_steps, 'mbedtls') && steps.cache-mbedtls-threadsafe.outputs.cache-hit != 'true' }} run: | curl --disable --fail --silent --show-error --connect-timeout 15 --max-time 120 --retry 6 --retry-connrefused \ --location "https://github.com/Mbed-TLS/mbedtls/releases/download/mbedtls-${MBEDTLS_VERSION}/mbedtls-${MBEDTLS_VERSION}.tar.bz2" | tar -xj @@ -455,9 +530,32 @@ jobs: cmake --build . cmake --install . - - name: 'cache openldap-static' + - name: 'cache mbedtls (prev)' + if: ${{ contains(matrix.build.install_steps, 'mbedtls-prev') }} + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 + id: cache-mbedtls-threadsafe-prev + env: + cache-name: cache-mbedtls-threadsafe-prev + with: + path: ~/mbedtls-prev + key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ env.MBEDTLS_VERSION }} + + - name: 'build mbedtls (prev)' + if: ${{ contains(matrix.build.install_steps, 'mbedtls-prev') && steps.cache-mbedtls-threadsafe-prev.outputs.cache-hit != 'true' }} + run: | + curl --disable --fail --silent --show-error --connect-timeout 15 --max-time 120 --retry 6 --retry-connrefused \ + --location "https://github.com/Mbed-TLS/mbedtls/releases/download/mbedtls-${MBEDTLS_VERSION_PREV}/mbedtls-${MBEDTLS_VERSION_PREV}.tar.bz2" | tar -xj + cd "mbedtls-${MBEDTLS_VERSION_PREV}" + ./scripts/config.py set MBEDTLS_THREADING_C + ./scripts/config.py set MBEDTLS_THREADING_PTHREAD + cmake -B . -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_INSTALL_PREFIX=/home/runner/mbedtls-prev \ + -DENABLE_PROGRAMS=OFF -DENABLE_TESTING=OFF + cmake --build . + cmake --install . + + - name: 'cache openldap (static)' if: ${{ contains(matrix.build.install_steps, 'openldap-static') }} - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-openldap-static env: cache-name: cache-openldap-static @@ -471,13 +569,12 @@ jobs: curl --disable --fail --silent --show-error --connect-timeout 15 --max-time 120 --retry 6 --retry-connrefused \ --location "https://www.openldap.org/software/download/OpenLDAP/openldap-release/openldap-${OPENLDAP_VERSION}.tgz" | tar -xz cd "openldap-${OPENLDAP_VERSION}" - ./configure --enable-static --disable-shared --prefix=/home/runner/openldap-static - make + ./configure --enable-static --disable-shared --disable-slapd --prefix=/home/runner/openldap-static make install - name: 'cache openssl (thread sanitizer)' if: ${{ contains(matrix.build.install_steps, 'openssl-tsan') }} - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-openssl-tsan env: cache-name: cache-openssl-tsan @@ -488,7 +585,7 @@ jobs: - name: 'build openssl (thread sanitizer)' if: ${{ contains(matrix.build.install_steps, 'openssl-tsan') && steps.cache-openssl-tsan.outputs.cache-hit != 'true' }} run: | - git clone --quiet --depth=1 -b "openssl-${OPENSSL_VERSION}" https://github.com/openssl/openssl + git clone --quiet --depth 1 -b "openssl-${OPENSSL_VERSION}" https://github.com/openssl/openssl cd openssl CC=clang CFLAGS='-fsanitize=thread' LDFLAGS='-fsanitize=thread' ./config --prefix=/home/runner/openssl --libdir=lib no-makedepend no-apps no-docs no-tests make @@ -496,7 +593,7 @@ jobs: - name: 'cache awslc' if: ${{ contains(matrix.build.install_steps, 'awslc') }} - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-awslc env: cache-name: cache-awslc @@ -516,7 +613,7 @@ jobs: - name: 'cache boringssl' if: ${{ contains(matrix.build.install_steps, 'boringssl') }} - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-boringssl env: cache-name: cache-boringssl @@ -537,7 +634,7 @@ jobs: - name: 'cache rustls' if: ${{ contains(matrix.build.install_steps, 'rustls') }} - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-rustls env: cache-name: cache-rustls @@ -555,7 +652,7 @@ jobs: rm ~/rustls/librustls.zip - name: 'build rustls' - # Note: we don't check cache-hit here. If the cache is hit, we still need to dpkg install the deb. + # Note: we do not check cache-hit here. If the cache is hit, we need to dpkg install the deb. if: ${{ contains(matrix.build.install_steps, 'rustls') }} run: sudo dpkg -i ~/rustls/"librustls_${RUSTLS_VERSION}_amd64.deb" @@ -570,7 +667,7 @@ jobs: source /opt/intel/oneapi/setvars.sh printenv >> "$GITHUB_ENV" - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false @@ -628,7 +725,7 @@ jobs: fi - name: 'single-use function check' - if: ${{ contains(matrix.build.configure, '--disable-unity') || contains(matrix.build.generate, '-DCMAKE_UNITY_BUILD=OFF') }} + if: ${{ (contains(matrix.build.configure, '--disable-unity') || contains(matrix.build.generate, '-DCMAKE_UNITY_BUILD=OFF')) && !contains(matrix.build.install_steps, 'filc') }} run: | git config --global --add safe.directory "*" if [ "${MATRIX_BUILD}" = 'cmake' ]; then @@ -667,16 +764,19 @@ jobs: - name: 'run tests' if: ${{ !contains(matrix.build.install_steps, 'skipall') && !contains(matrix.build.install_steps, 'skiprun') }} - timeout-minutes: ${{ contains(matrix.build.install_packages, 'valgrind') && 30 || 15 }} + timeout-minutes: ${{ contains(matrix.build.install_packages, 'valgrind') && 20 || 10 }} env: TEST_TARGET: ${{ matrix.build.torture && 'test-torture' || 'test-ci' }} TFLAGS: '${{ matrix.build.tflags }}' run: | if [ "${TEST_TARGET}" = 'test-ci' ] && [[ "${MATRIX_INSTALL_PACKAGES}" = *'valgrind'* ]]; then TFLAGS+=' -j6' + TFLAGS+=' !776' # skip long-running flaky test if [[ "${MATRIX_INSTALL_PACKAGES}" = *'libgss-dev'* ]]; then TFLAGS+=' ~2077 ~2078' # memory leaks from Curl_auth_decode_spnego_message() -> gss_init_sec_context() fi + elif [ "${TEST_TARGET}" != 'test-ci' ]; then + TFLAGS+=' --buildinfo' # only test-ci sets this by default, set it manually for test-torture fi [ -f ~/venv/bin/activate ] && source ~/venv/bin/activate if [[ "${MATRIX_INSTALL_STEPS}" = *'codeset-test'* ]]; then diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 1e9f2408a8ba..77bd81ea855f 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -44,6 +44,7 @@ permissions: {} env: CURL_CI: github + CURL_TEST_MIN: 1700 MAKEFLAGS: -j 4 LDFLAGS: -w # suppress 'object file was built for newer macOS version than being linked' warnings @@ -54,12 +55,12 @@ jobs: timeout-minutes: 10 env: DEVELOPER_DIR: "/Applications/Xcode${{ matrix.build.xcode && format('_{0}', matrix.build.xcode) || '' }}.app/Contents/Developer" - CC: ${{ matrix.build.compiler || 'clang' }} + CC: 'clang' LDFLAGS: '' MATRIX_BUILD: ${{ matrix.build.generate && 'cmake' || 'autotools' }} MATRIX_OPTIONS: ${{ matrix.build.options }} # renovate: datasource=github-tags depName=libressl/portable versioning=semver registryUrl=https://github.com - LIBRESSL_VERSION: 4.2.0 + LIBRESSL_VERSION: 4.2.1 strategy: fail-fast: false matrix: @@ -81,6 +82,7 @@ jobs: - name: 'libressl' install_steps: libressl generator: Xcode + xcode: '' # default Xcode. Set it once to silence actionlint. options: --config Debug generate: >- -DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED=OFF @@ -93,6 +95,7 @@ jobs: steps: - name: 'brew install' if: ${{ matrix.build.configure }} + timeout-minutes: 5 run: | # shellcheck disable=SC2181,SC2034 while [[ $? == 0 ]]; do for i in 1 2 3; do if brew update && brew install automake libtool; then break 2; else echo Error: wait to try again; sleep 10; fi; done; false Too many retries; done @@ -110,7 +113,7 @@ jobs: - name: 'cache libressl' if: ${{ contains(matrix.build.install_steps, 'libressl') }} - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-libressl env: cache-name: cache-libressl @@ -134,7 +137,7 @@ jobs: cmake --build . cmake --install . --verbose - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false @@ -183,7 +186,7 @@ jobs: fi - name: 'curl info' - run: find . -type f \( -name curl -o -name '*.dylib' -o -name '*.a' \) -exec file '{}' \; + run: find . -type f \( -name curl -o -name '*.dylib' -o -name '*.a' \) -exec file -- '{}' \; - name: 'build tests' run: | @@ -204,7 +207,7 @@ jobs: macos: name: "${{ matrix.build.generate && 'CM' || 'AM' }} ${{ matrix.compiler }} ${{ matrix.build.name }}" runs-on: 'macos-15' - timeout-minutes: 45 + timeout-minutes: 25 env: DEVELOPER_DIR: "/Applications/Xcode${{ matrix.build.xcode && format('_{0}', matrix.build.xcode) || '' }}.app/Contents/Developer" CC: '${{ matrix.compiler }}' @@ -216,22 +219,27 @@ jobs: strategy: fail-fast: false matrix: - compiler: [clang, llvm@18, gcc-12] + compiler: [clang, llvm@18, gcc-13] build: # autotools - name: '!ssl !debug brotli zstd' compiler: clang install: brotli zstd configure: --without-ssl --with-brotli --with-zstd + tflags: '--min=1450' + xcode: '' # default Xcode. Set it once to silence actionlint. - name: '!ssl !debug' - compiler: gcc-12 + compiler: gcc-13 configure: --without-ssl + tflags: '--min=950' - name: '!ssl' compiler: clang configure: --enable-debug --without-ssl + tflags: '--min=1500' - name: '!ssl libssh2 AppleIDN' compiler: clang configure: --enable-debug --with-libssh2=/opt/homebrew/opt/libssh2 --without-ssl --with-apple-idn + tflags: '--min=1550' - name: 'OpenSSL libssh c-ares' compiler: clang install: libssh @@ -243,8 +251,10 @@ jobs: - name: '!ssl c-ares' compiler: clang configure: --enable-debug --enable-ares --without-ssl + tflags: '--min=1500' - name: '!ssl HTTP-only' compiler: clang + tflags: '--min=950' configure: >- --enable-debug --disable-alt-svc --disable-dict --disable-file --disable-ftp --disable-gopher --disable-imap @@ -274,7 +284,7 @@ jobs: - name: 'OpenSSL event-based' compiler: clang configure: --enable-debug --with-openssl=/opt/homebrew/opt/openssl - tflags: --test-event + tflags: '--test-event --min=1300' # cmake - name: 'OpenSSL gsasl rtmp AppleIDN SecTrust +examples' install: libnghttp3 libngtcp2 gsasl rtmpdump @@ -318,36 +328,38 @@ jobs: install: gnutls nettle krb5 generate: -DENABLE_DEBUG=ON -DCURL_USE_GNUTLS=ON -DCURL_USE_OPENSSL=OFF -DCURL_USE_GSSAPI=ON -DGSS_ROOT_DIR=/opt/homebrew/opt/krb5 -DCURL_DISABLE_LDAP=ON -DUSE_SSLS_EXPORT=ON - name: 'aws-lc' - compiler: gcc-12 + compiler: gcc-13 install: aws-lc generate: -DENABLE_DEBUG=ON -DCURL_USE_OPENSSL=ON -DOPENSSL_ROOT_DIR=/opt/homebrew/opt/aws-lc -DUSE_ECH=ON -DCURL_DISABLE_LDAP=ON -DUSE_SSLS_EXPORT=ON - name: 'Rustls' compiler: clang install: rustls-ffi generate: -DENABLE_DEBUG=ON -DCURL_USE_RUSTLS=ON -DUSE_ECH=ON -DCURL_DISABLE_LDAP=ON + tflags: '--min=1650' - name: 'OpenSSL torture !FTP' compiler: clang install: libnghttp3 install_steps: torture generate: -DENABLE_DEBUG=ON -DBUILD_SHARED_LIBS=OFF -DENABLE_THREADED_RESOLVER=OFF -DOPENSSL_ROOT_DIR=/opt/homebrew/opt/openssl -DUSE_OPENSSL_QUIC=ON - tflags: -t --shallow=25 !FTP + tflags: '-t --shallow=25 !FTP --min=1450' - name: 'OpenSSL torture FTP' compiler: clang install: libnghttp3 install_steps: torture generate: -DENABLE_DEBUG=ON -DBUILD_SHARED_LIBS=OFF -DENABLE_THREADED_RESOLVER=OFF -DOPENSSL_ROOT_DIR=/opt/homebrew/opt/openssl -DUSE_OPENSSL_QUIC=ON - tflags: -t --shallow=20 FTP + tflags: '-t --shallow=20 FTP --min=260' exclude: # opt out jobs from combinations that have the compiler set manually - { compiler: llvm@18, build: { compiler: 'clang' } } - - { compiler: llvm@18, build: { compiler: 'gcc-12' } } - - { compiler: gcc-12, build: { compiler: 'clang' } } - - { compiler: gcc-12, build: { compiler: 'llvm@18' } } - - { compiler: clang, build: { compiler: 'gcc-12' } } + - { compiler: llvm@18, build: { compiler: 'gcc-13' } } + - { compiler: gcc-13, build: { compiler: 'clang' } } + - { compiler: gcc-13, build: { compiler: 'llvm@18' } } + - { compiler: clang, build: { compiler: 'gcc-13' } } - { compiler: clang, build: { compiler: 'llvm@18' } } steps: - name: 'brew install' + timeout-minutes: 5 # 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 @@ -381,7 +393,7 @@ jobs: echo '::group::macros predefined'; "${CC}" -dM -E - < /dev/null | sort || true; echo '::endgroup::' echo '::group::brew packages installed'; ls -l /opt/homebrew/opt; echo '::endgroup::' - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false @@ -495,6 +507,9 @@ jobs: TFLAGS: '${{ matrix.build.tflags }}' run: | TFLAGS="-j20 ${TFLAGS}" + if [ "${TEST_TARGET}" != 'test-ci' ]; then + TFLAGS+=' --buildinfo' # only test-ci sets this by default, set it manually for test-torture + fi source ~/venv/bin/activate if [[ "${MATRIX_INSTALL_STEPS}" = *'codeset-test'* ]]; then locale || true @@ -538,7 +553,7 @@ jobs: fi combinations: # Test buildability with host OS, Xcode / SDK, compiler, target-OS, built tool, combinations - name: "${{ matrix.build == 'cmake' && 'CM' || 'AM' }} ${{ matrix.compiler }} ${{ matrix.image }} ${{ matrix.xcode }} ${{ matrix.config }}" + name: "${{ matrix.build == 'cmake' && 'CM' || 'AM' }} ${{ matrix.compiler }} ${{ matrix.image }} ${{ matrix.xcode }}" runs-on: ${{ matrix.image }} timeout-minutes: 10 env: @@ -555,7 +570,7 @@ jobs: # https://github.com/actions/runner-images/blob/main/images/macos/macos-14-arm64-Readme.md # https://github.com/actions/runner-images/blob/main/images/macos/macos-15-arm64-Readme.md # https://github.com/actions/runner-images/blob/main/images/macos/macos-26-arm64-Readme.md - compiler: [gcc-12, gcc-13, gcc-15, llvm@15, llvm@18, llvm@20, clang] + compiler: [gcc-13, gcc-14, gcc-15, llvm@15, llvm@18, llvm@20, clang] # Xcode support matrix as of 2025-10, with default macOS SDK versions and OS names, years: # * = default Xcode on the runner. # macos-14: 15.0.1, 15.1, 15.2, 15.3,*15.4 @@ -566,47 +581,20 @@ jobs: # https://github.com/actions/runner-images/tree/main/images/macos # https://en.wikipedia.org/wiki/MacOS_version_history image: [macos-14, macos-15, macos-26] - # Can skip these to reduce jobs: - # 15.1 has the same default macOS SDK as 15.2 and identical test results. - # 15.4 not revealing new fallouts. - #xcode: ['15.0.1', '15.1', '15.2', '15.3', '15.4', '16.0', '16.1'] # all Xcode - #xcode: ['15.0.1' , '15.2', '15.3', '15.4', '16.0', '16.1'] # all SDK - #xcode: ['15.0.1' , '15.2', '15.3' , '16.0' ] # coverage xcode: [''] # default Xcodes macos-version-min: [''] build: [autotools, cmake] exclude: # Combinations not covered by runner images: - - { image: macos-14, xcode: '16.0' } - - { image: macos-14, xcode: '16.1' } - - { image: macos-14, xcode: '16.2' } - - { image: macos-14, xcode: '16.3' } - - { image: macos-14, xcode: '16.4' } - - { image: macos-14, xcode: '26.0' } - - { image: macos-15, xcode: '15.0.1' } - - { image: macos-15, xcode: '15.1' } - - { image: macos-15, xcode: '15.2' } - - { image: macos-15, xcode: '15.3' } - - { image: macos-15, xcode: '15.4' } - - { image: macos-26, xcode: '15.0.1' } - - { image: macos-26, xcode: '15.1' } - - { image: macos-26, xcode: '15.2' } - - { image: macos-26, xcode: '15.3' } - - { image: macos-26, xcode: '15.4' } - - { image: macos-26, xcode: '16.0' } - - { image: macos-26, xcode: '16.1' } - - { image: macos-26, xcode: '16.2' } - - { image: macos-26, xcode: '16.3' } - { image: macos-14, compiler: 'llvm@18' } - { image: macos-14, compiler: 'llvm@20' } - { image: macos-15, compiler: 'llvm@15' } - { image: macos-15, compiler: 'llvm@20' } - { image: macos-26, compiler: 'llvm@15' } - { image: macos-26, compiler: 'llvm@18' } - - { image: macos-26, compiler: 'gcc-12' } # Reduce build combinations, by dropping less interesting ones - - { compiler: gcc-13, build: cmake } - - { compiler: gcc-14, build: autotools } + - { image: macos-26, compiler: 'gcc-13' } + - { compiler: gcc-14, build: cmake } - { compiler: gcc-15, build: autotools } steps: - name: 'install autotools' @@ -628,7 +616,7 @@ jobs: echo '::group::macros predefined'; "${CC}" -dM -E - < /dev/null | sort || true; echo '::endgroup::' echo '::group::brew packages preinstalled'; ls -l /opt/homebrew/opt; echo '::endgroup::' - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false @@ -638,7 +626,7 @@ jobs: - name: 'configure / ${{ matrix.build }}' run: | - if [ "${MATRIX_COMPILER}" = 'gcc-13' ] && [ "${MATRIX_IMAGE}" = 'macos-15' ] ; then + if [ "${MATRIX_COMPILER}" = 'gcc-13' ] && [ "${MATRIX_IMAGE}" = 'macos-15' ]; then # Ref: https://github.com/Homebrew/homebrew-core/issues/194778#issuecomment-2793243409 /opt/homebrew/opt/gcc@13/libexec/gcc/aarch64-apple-darwin24/13/install-tools/mkheaders fi diff --git a/.github/workflows/non-native.yml b/.github/workflows/non-native.yml index 8dccb9e39964..e1b675aa2ccb 100644 --- a/.github/workflows/non-native.yml +++ b/.github/workflows/non-native.yml @@ -37,6 +37,7 @@ permissions: {} env: CURL_CI: github + CURL_TEST_MIN: 1750 jobs: netbsd: @@ -47,15 +48,15 @@ jobs: matrix: arch: ['x86_64'] steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - name: 'cmake' - uses: cross-platform-actions/action@e8a7b572196ff79ded1979dc2bb9ee67d1ddb252 # v0.29.0 + uses: cross-platform-actions/action@46e8d7fb25520a8d6c64fd2b7a1192611da98eda # v0.30.0 env: MATRIX_ARCH: '${{ matrix.arch }}' with: - environment_variables: MATRIX_ARCH + environment_variables: CURL_CI CURL_TEST_MIN MATRIX_ARCH operating_system: 'netbsd' version: '10.1' architecture: ${{ matrix.arch }} @@ -92,15 +93,15 @@ jobs: matrix: arch: ['x86_64'] steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - name: 'cmake' - uses: cross-platform-actions/action@e8a7b572196ff79ded1979dc2bb9ee67d1ddb252 # v0.29.0 + uses: cross-platform-actions/action@46e8d7fb25520a8d6c64fd2b7a1192611da98eda # v0.30.0 env: MATRIX_ARCH: '${{ matrix.arch }}' with: - environment_variables: MATRIX_ARCH + environment_variables: CURL_CI CURL_TEST_MIN MATRIX_ARCH operating_system: 'openbsd' version: '7.7' architecture: ${{ matrix.arch }} @@ -138,23 +139,24 @@ jobs: include: - { build: 'autotools', arch: 'x86_64', compiler: 'clang' } - { build: 'cmake' , arch: 'x86_64', compiler: 'clang', options: '-DCMAKE_UNITY_BUILD=OFF', desc: ' !unity !runtests !examples' } - - { build: 'autotools', arch: 'arm64', compiler: 'clang' } - - { build: 'cmake' , arch: 'arm64', compiler: 'clang' } + - { build: 'autotools', arch: 'arm64' , compiler: 'clang' } + - { build: 'cmake' , arch: 'arm64' , compiler: 'clang' } fail-fast: false steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false - name: '${{ matrix.build }}' - uses: cross-platform-actions/action@e8a7b572196ff79ded1979dc2bb9ee67d1ddb252 # v0.29.0 + uses: cross-platform-actions/action@46e8d7fb25520a8d6c64fd2b7a1192611da98eda # v0.30.0 env: CC: '${{ matrix.compiler }}' + CURL_TEST_MIN: 1800 MATRIX_ARCH: '${{ matrix.arch }}' MATRIX_BUILD: '${{ matrix.build }}' MATRIX_DESC: '${{ matrix.desc }}' MATRIX_OPTIONS: '${{ matrix.options }}' with: - environment_variables: CC MATRIX_ARCH MATRIX_BUILD MATRIX_DESC MATRIX_OPTIONS + environment_variables: CC CURL_CI CURL_TEST_MIN MATRIX_ARCH MATRIX_BUILD MATRIX_DESC MATRIX_OPTIONS operating_system: 'freebsd' version: '14.3' architecture: ${{ matrix.arch }} @@ -261,7 +263,7 @@ jobs: fail-fast: false steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false @@ -310,7 +312,7 @@ jobs: fi - name: 'curl info' - run: find . -type f \( -name curl -o -name '*.so' -o -name '*.a' \) -exec file '{}' \; + run: find . -type f \( -name curl -o -name '*.so' -o -name '*.a' \) -exec file -- '{}' \; - name: 'build tests' run: | diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 975b592c7ce1..700913e092f8 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -37,6 +37,7 @@ permissions: {} env: CURL_CI: github + CURL_TEST_MIN: 1700 jobs: cygwin: @@ -57,8 +58,6 @@ jobs: - { build: 'cmake' , platform: 'x86_64', tflags: '' , config: '-DENABLE_DEBUG=ON -DCURL_USE_OPENSSL=ON -DENABLE_THREADED_RESOLVER=OFF', install: 'libssl-devel libssh2-devel', name: 'openssl' } fail-fast: false steps: - - run: git config --global core.autocrlf input - shell: pwsh - uses: cygwin/cygwin-install-action@f2009323764960f80959895c7bc3bb30210afe4d # v6 with: platform: ${{ matrix.platform }} @@ -76,7 +75,7 @@ jobs: libnghttp2-devel ${{ matrix.install }} - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false @@ -134,7 +133,7 @@ jobs: timeout-minutes: 1 run: | PATH=/usr/bin - find . \( -name '*.exe' -o -name '*.dll' -o -name '*.a' \) -exec file '{}' \; + find . \( -name '*.exe' -o -name '*.dll' -o -name '*.a' \) -exec file -- '{}' \; if [ "${MATRIX_BUILD}" = 'cmake' ]; then PATH="$PWD/bld/lib:$PATH" fi @@ -199,31 +198,30 @@ jobs: matrix: include: # MSYS - - { build: 'autotools', sys: 'msys' , env: 'x86_64' , tflags: '' , config: '--enable-debug --with-openssl --disable-threaded-resolver --disable-proxy', install: 'openssl-devel libssh2-devel', name: '!proxy' } - - { build: 'autotools', sys: 'msys' , env: 'x86_64' , tflags: 'skiprun', config: '--enable-debug --with-openssl --disable-threaded-resolver', install: 'openssl-devel libssh2-devel', name: 'default' } - - { build: 'cmake' , sys: 'msys' , env: 'x86_64' , tflags: '' , config: '-DENABLE_DEBUG=ON -DENABLE_THREADED_RESOLVER=OFF', install: 'openssl-devel libssh2-devel', name: 'default' } - - { build: 'autotools', sys: 'msys' , env: 'x86_64' , tflags: '' , config: '--with-openssl', install: 'openssl-devel libssh2-devel', name: 'default R' } + - { build: 'autotools', sys: 'msys' , env: 'x86_64' , tflags: '--min=1550', config: '--enable-debug --with-openssl --disable-threaded-resolver --disable-proxy', install: 'openssl-devel libssh2-devel', name: '!proxy' } + - { build: 'autotools', sys: 'msys' , env: 'x86_64' , tflags: 'skiprun' , config: '--enable-debug --with-openssl --disable-threaded-resolver', install: 'openssl-devel libssh2-devel', name: 'default' } + - { build: 'cmake' , sys: 'msys' , env: 'x86_64' , tflags: '' , config: '-DENABLE_DEBUG=ON -DENABLE_THREADED_RESOLVER=OFF', install: 'openssl-devel libssh2-devel', name: 'default' } + - { build: 'autotools', sys: 'msys' , env: 'x86_64' , tflags: '' , config: '--with-openssl', install: 'openssl-devel libssh2-devel', name: 'default R' } # MinGW - - { build: 'autotools', sys: 'mingw64' , env: 'x86_64' , tflags: 'skiprun', config: '--enable-debug --with-openssl --disable-threaded-resolver --disable-curldebug --enable-static=no --without-zlib CPPFLAGS=-D_WIN32_WINNT=0x0501', install: 'mingw-w64-x86_64-openssl mingw-w64-x86_64-libssh2', name: 'default XP' } - - { build: 'autotools', sys: 'mingw64' , env: 'x86_64' , tflags: '' , config: '--enable-debug --with-openssl --enable-windows-unicode --enable-ares --with-openssl-quic --enable-shared=no', install: 'mingw-w64-x86_64-openssl mingw-w64-x86_64-nghttp3 mingw-w64-x86_64-libssh2', name: 'c-ares U' } - - { build: 'cmake' , sys: 'mingw64' , env: 'x86_64' , tflags: '' , config: '-DENABLE_DEBUG=ON -DBUILD_SHARED_LIBS=OFF -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=ON -DENABLE_ARES=ON', install: 'mingw-w64-x86_64-libssh2', type: 'Debug', name: 'schannel c-ares U' } + - { build: 'autotools', sys: 'mingw64' , env: 'x86_64' , tflags: 'skiprun' , config: '--enable-debug --with-openssl --disable-threaded-resolver --disable-curldebug --enable-static=no --without-zlib CPPFLAGS=-D_WIN32_WINNT=0x0501', install: 'mingw-w64-x86_64-openssl mingw-w64-x86_64-libssh2', name: 'default XP' } + - { build: 'autotools', sys: 'mingw64' , env: 'x86_64' , tflags: '' , config: '--enable-debug --with-openssl --enable-windows-unicode --enable-ares --with-openssl-quic --enable-shared=no', install: 'mingw-w64-x86_64-c-ares mingw-w64-x86_64-openssl mingw-w64-x86_64-nghttp3 mingw-w64-x86_64-libssh2', name: 'c-ares U' } + - { build: 'cmake' , sys: 'mingw64' , env: 'x86_64' , tflags: '--min=1650', config: '-DENABLE_DEBUG=ON -DBUILD_SHARED_LIBS=OFF -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=ON -DENABLE_ARES=ON', install: 'mingw-w64-x86_64-c-ares mingw-w64-x86_64-libssh2', type: 'Debug', name: 'schannel c-ares U' } + # MinGW torture + - { build: 'cmake' , sys: 'mingw64' , env: 'x86_64' , tflags: '-t --shallow=13 !FTP --min=1300', config: '-DENABLE_DEBUG=ON -DBUILD_SHARED_LIBS=OFF -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=ON -DENABLE_ARES=ON', install: 'mingw-w64-x86_64-c-ares mingw-w64-x86_64-libssh2', type: 'Debug', name: 'schannel U torture' } # WARNING: libssh uses hard-coded world-writable paths (/etc/..., ~/.ssh/) to # read its configuration from, making it vulnerable to attacks on # Windows. Do not use this component till there is a fix for these. # https://github.com/curl/curl-for-win/blob/3951808deb04df9489ee17430f236ed54436f81a/libssh.sh#L6-L8 - - { build: 'cmake' , sys: 'clang64' , env: 'clang-x86_64' , tflags: '' , config: '-DENABLE_DEBUG=ON -DBUILD_SHARED_LIBS=OFF -DCURL_USE_GNUTLS=ON -DENABLE_UNICODE=OFF -DUSE_NGTCP2=ON -DCURL_USE_LIBSSH2=OFF -DCURL_USE_LIBSSH=ON', install: 'mingw-w64-clang-x86_64-gnutls mingw-w64-clang-x86_64-nghttp3 mingw-w64-clang-x86_64-ngtcp2 mingw-w64-clang-x86_64-libssh', type: 'Debug', name: 'gnutls libssh' } - - { build: 'cmake' , sys: 'clangarm64', env: 'clang-aarch64', tflags: 'skiprun', config: '-DENABLE_DEBUG=OFF -DBUILD_SHARED_LIBS=ON -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=ON -DENABLE_CURLDEBUG=ON', install: 'mingw-w64-clang-aarch64-libssh2', type: 'Release', name: 'schannel R TrackMemory', image: 'windows-11-arm' } - - { build: 'cmake' , sys: 'clang64' , env: 'clang-x86_64' , tflags: 'skiprun', config: '-DENABLE_DEBUG=ON -DBUILD_SHARED_LIBS=OFF -DCURL_USE_OPENSSL=ON -DENABLE_UNICODE=OFF -DUSE_NGTCP2=ON', install: 'mingw-w64-clang-x86_64-openssl mingw-w64-clang-x86_64-nghttp3 mingw-w64-clang-x86_64-ngtcp2 mingw-w64-clang-x86_64-libssh2', type: 'Release', name: 'openssl', chkprefill: '_chkprefill' } - - { build: 'cmake' , sys: 'ucrt64' , env: 'ucrt-x86_64' , tflags: 'skiprun', config: '-DENABLE_DEBUG=OFF -DBUILD_SHARED_LIBS=ON -DCURL_USE_OPENSSL=ON', install: 'mingw-w64-ucrt-x86_64-openssl mingw-w64-ucrt-x86_64-libssh2', type: 'Release', test: 'uwp', name: 'schannel' } - # { build: 'autotools', sys: 'ucrt64' , env: 'ucrt-x86_64' , tflags: 'skiprun', config: '--without-debug --with-schannel --enable-shared', install: 'mingw-w64-ucrt-x86_64-libssh2', type: 'Release', test: 'uwp', name: 'schannel' } - - { build: 'cmake' , sys: 'mingw64' , env: 'x86_64' , tflags: 'skiprun', config: '-DENABLE_DEBUG=ON -DBUILD_SHARED_LIBS=ON -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=ON -DCMAKE_VERBOSE_MAKEFILE=ON', install: 'mingw-w64-x86_64-libssh2', type: 'Debug', cflags: '-DCURL_SCHANNEL_DEV_DEBUG', name: 'schannel dev debug', image: 'windows-2025' } - - { build: 'cmake' , sys: 'mingw32' , env: 'i686' , tflags: 'skiprun', config: '-DENABLE_DEBUG=OFF -DBUILD_SHARED_LIBS=ON -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=ON', install: 'mingw-w64-i686-libssh2', type: 'Release', name: 'schannel R' } + - { build: 'cmake' , sys: 'clang64' , env: 'clang-x86_64' , tflags: '' , config: '-DENABLE_DEBUG=ON -DBUILD_SHARED_LIBS=OFF -DCURL_USE_GNUTLS=ON -DENABLE_UNICODE=OFF -DUSE_NGTCP2=ON -DCURL_USE_LIBSSH2=OFF -DCURL_USE_LIBSSH=ON', install: 'mingw-w64-clang-x86_64-gnutls mingw-w64-clang-x86_64-nghttp3 mingw-w64-clang-x86_64-ngtcp2 mingw-w64-clang-x86_64-libssh', type: 'Debug', name: 'gnutls libssh' } + - { build: 'cmake' , sys: 'clangarm64', env: 'clang-aarch64', tflags: 'skiprun' , config: '-DENABLE_DEBUG=OFF -DBUILD_SHARED_LIBS=ON -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=ON -DENABLE_CURLDEBUG=ON', install: 'mingw-w64-clang-aarch64-libssh2', type: 'Release', name: 'schannel R TrackMemory', image: 'windows-11-arm' } + - { build: 'cmake' , sys: 'clang64' , env: 'clang-x86_64' , tflags: 'skiprun' , config: '-DENABLE_DEBUG=ON -DBUILD_SHARED_LIBS=OFF -DCURL_USE_OPENSSL=ON -DENABLE_UNICODE=OFF -DUSE_NGTCP2=ON', install: 'mingw-w64-clang-x86_64-openssl mingw-w64-clang-x86_64-nghttp3 mingw-w64-clang-x86_64-ngtcp2 mingw-w64-clang-x86_64-libssh2', type: 'Release', name: 'openssl', chkprefill: '_chkprefill' } + - { build: 'cmake' , sys: 'ucrt64' , env: 'ucrt-x86_64' , tflags: 'skiprun' , config: '-DENABLE_DEBUG=OFF -DBUILD_SHARED_LIBS=ON -DCURL_USE_OPENSSL=ON', install: 'mingw-w64-ucrt-x86_64-openssl mingw-w64-ucrt-x86_64-libssh2', type: 'Release', test: 'uwp', name: 'schannel' } + # { build: 'autotools', sys: 'ucrt64' , env: 'ucrt-x86_64' , tflags: 'skiprun' , config: '--without-debug --with-schannel --enable-shared', install: 'mingw-w64-ucrt-x86_64-libssh2', type: 'Release', test: 'uwp', name: 'schannel' } + - { build: 'cmake' , sys: 'mingw64' , env: 'x86_64' , tflags: 'skiprun' , config: '-DENABLE_DEBUG=ON -DBUILD_SHARED_LIBS=ON -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=ON -DCMAKE_VERBOSE_MAKEFILE=ON', install: 'mingw-w64-x86_64-libssh2', type: 'Debug', cflags: '-DCURL_SCHANNEL_DEV_DEBUG', name: 'schannel dev debug', image: 'windows-2025' } + - { build: 'cmake' , sys: 'mingw32' , env: 'i686' , tflags: 'skiprun' , config: '-DENABLE_DEBUG=OFF -DBUILD_SHARED_LIBS=ON -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=ON', install: 'mingw-w64-i686-libssh2', type: 'Release', name: 'schannel R' } fail-fast: false steps: - - run: git config --global core.autocrlf input - shell: pwsh - - - uses: msys2/setup-msys2@fb197b72ce45fb24f17bf3f807a388985654d1f2 # v2.29.0 + - uses: msys2/setup-msys2@4f806de0a5a7294ffabaff804b38a9b435a73bda # v2.30.0 if: ${{ matrix.sys == 'msys' }} with: msystem: ${{ matrix.sys }} @@ -239,20 +237,18 @@ jobs: libpsl-devel ${{ matrix.install }} - - uses: msys2/setup-msys2@fb197b72ce45fb24f17bf3f807a388985654d1f2 # v2.29.0 + - uses: msys2/setup-msys2@4f806de0a5a7294ffabaff804b38a9b435a73bda # v2.30.0 if: ${{ matrix.sys != 'msys' }} with: msystem: ${{ matrix.sys }} - update: ${{ matrix.sys == 'clangarm64' }} # delete this line on next msys2/setup-msys2 bump install: >- mingw-w64-${{ matrix.env }}-cc mingw-w64-${{ matrix.env }}-${{ matrix.build }} ${{ matrix.build == 'autotools' && 'make' || '' }} mingw-w64-${{ matrix.env }}-diffutils mingw-w64-${{ matrix.env }}-libpsl - mingw-w64-${{ matrix.env }}-c-ares ${{ matrix.install }} - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false @@ -342,7 +338,7 @@ jobs: # avoid libtool's curl.exe wrapper for shared builds mv bld/src/.libs/curl.exe bld/src/curl.exe || true fi - find . \( -name '*.exe' -o -name '*.dll' -o -name '*.a' \) -exec file '{}' \; + find . \( -name '*.exe' -o -name '*.dll' -o -name '*.a' \) -exec file -- '{}' \; if [ "${MATRIX_TEST}" != 'uwp' ]; then # curl: error initializing curl library bld/src/curl.exe --disable --version fi @@ -370,11 +366,10 @@ jobs: run: | /usr/bin/pacman --noconfirm --noprogressbar --sync --needed openssh /c/ProgramData/chocolatey/choco.exe install --yes --no-progress --limit-output --timeout 180 --force stunnel || true - perl --version | tee "$GITHUB_WORKSPACE"/perlversion - name: 'run tests' if: ${{ matrix.tflags != 'skipall' && matrix.tflags != 'skiprun' }} - timeout-minutes: 10 + timeout-minutes: ${{ contains(matrix.tflags, '-t') && 15 || 10 }} env: MATRIX_INSTALL: '${{ matrix.install }}' TFLAGS: '${{ matrix.tflags }}' @@ -385,6 +380,9 @@ jobs: if [[ "${MATRIX_INSTALL}" = *'libssh2-wincng'* ]]; then TFLAGS+=' ~SCP ~SFTP' # Flaky: `-8, Unable to exchange encryption keys`. https://github.com/libssh2/libssh2/issues/804 fi + if [[ "${TFLAGS}" = *'-t'* ]]; then + TFLAGS+=' !2300' # Leaks memory and file handle via tool_doswin.c / win32_stdin_read_thread() + fi fi if [ -x "$(cygpath "${SYSTEMROOT}/System32/curl.exe")" ]; then TFLAGS+=" -ac $(cygpath "${SYSTEMROOT}/System32/curl.exe")" @@ -419,27 +417,31 @@ jobs: run: shell: msys2 {0} env: + CURL_TEST_MIN: 1550 MAKEFLAGS: -j 5 MATRIX_DIR: '${{ matrix.dir }}' strategy: matrix: include: - name: 'schannel' # mingw-w64 12.0 - dir: 'mingw64' + sys: 'mingw64' + dir: 'w64devkit' env: 'x86_64' - ver: '15.0.1' - url: 'https://github.com/brechtsanders/winlibs_mingw/releases/download/15.0.1-snapshot20250406posix-12.0.0-ucrt-r1/winlibs-x86_64-posix-seh-gcc-15.0.1-snapshot20250406-mingw-w64ucrt-12.0.0-r1.7z' - config: '-DENABLE_DEBUG=ON -DBUILD_SHARED_LIBS=OFF -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=OFF' + ver: '15.1.0' + url: 'https://github.com/skeeto/w64devkit/releases/download/v2.2.0/w64devkit-x64-2.2.0.7z.exe' + config: '-DENABLE_DEBUG=ON -DBUILD_SHARED_LIBS=OFF -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=OFF -DENABLE_UNIX_SOCKETS=OFF' type: 'Release' - tflags: 'skiprun' - name: 'schannel' # mingw-w64 10.0 + sys: 'mingw64' dir: 'mingw64' env: 'x86_64' ver: '9.5.0' url: 'https://github.com/brechtsanders/winlibs_mingw/releases/download/9.5.0-10.0.0-msvcrt-r1/winlibs-x86_64-posix-seh-gcc-9.5.0-mingw-w64msvcrt-10.0.0-r1.7z' config: '-DENABLE_DEBUG=ON -DBUILD_SHARED_LIBS=OFF -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=OFF' type: 'Release' + tflags: 'skiprun' - name: 'schannel mbedtls U' # mingw-w64 6.0 + sys: 'mingw64' dir: 'mingw64' env: 'x86_64' ver: '7.3.0' @@ -449,6 +451,7 @@ jobs: type: 'Release' tflags: 'skiprun' - name: 'schannel !unity' # mingw-w64 5.0 + sys: 'mingw32' dir: 'mingw32' env: 'i686' ver: '6.4.0' @@ -457,6 +460,7 @@ jobs: type: 'Debug' tflags: 'skiprun' - name: 'schannel !examples' # mingw-w64 3.0 + sys: 'mingw64' dir: 'mingw64' env: 'x86_64' ver: '4.8.1' @@ -464,11 +468,12 @@ jobs: config: '-DENABLE_DEBUG=ON -DBUILD_SHARED_LIBS=OFF -DCURL_USE_SCHANNEL=ON' type: 'Debug' tflags: 'skipall' + chkprefill: '' # Set it once to silence actionlint fail-fast: false steps: - - uses: msys2/setup-msys2@fb197b72ce45fb24f17bf3f807a388985654d1f2 # v2.29.0 + - uses: msys2/setup-msys2@4f806de0a5a7294ffabaff804b38a9b435a73bda # v2.30.0 with: - msystem: ${{ matrix.dir }} + msystem: ${{ matrix.sys }} release: false update: false cache: false @@ -478,7 +483,7 @@ jobs: ${{ matrix.install }} - name: 'cache compiler (gcc ${{ matrix.ver }}-${{ matrix.env }})' - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb # v5.0.1 id: cache-compiler with: path: D:\my-cache @@ -500,9 +505,7 @@ jobs: rm -r -f pack.bin ls -l - - run: git config --global core.autocrlf input - - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false @@ -550,7 +553,7 @@ jobs: - name: 'curl -V' timeout-minutes: 1 run: | - /usr/bin/find . \( -name '*.exe' -o -name '*.dll' -o -name '*.a' \) -exec file '{}' \; + /usr/bin/find . \( -name '*.exe' -o -name '*.dll' -o -name '*.a' \) -exec file -- '{}' \; PATH="$PWD/bld/lib:$PATH" bld/src/curl.exe --disable --version @@ -567,7 +570,6 @@ jobs: run: | /c/ProgramData/chocolatey/choco.exe install --yes --no-progress --limit-output --timeout 180 --force stunnel || true python3 -m pip --disable-pip-version-check --no-input --no-cache-dir install --progress-bar off --prefer-binary -r tests/requirements.txt - perl --version | tee "$GITHUB_WORKSPACE"/perlversion - name: 'run tests' if: ${{ matrix.tflags != 'skipall' && matrix.tflags != 'skiprun' }} @@ -616,7 +618,7 @@ jobs: sudo rm -f /var/lib/man-db/auto-update sudo apt-get -o Dpkg::Use-Pty=0 install gcc-mingw-w64-x86-64-win32 - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false @@ -670,7 +672,7 @@ jobs: fi - name: 'curl info' - run: find . \( -name '*.exe' -o -name '*.dll' -o -name '*.a' \) -exec file '{}' \; + run: find . \( -name '*.exe' -o -name '*.dll' -o -name '*.a' \) -exec file -- '{}' \; - name: 'build tests' if: ${{ matrix.build == 'cmake' && matrix.compiler != 'clang-tidy' }} # Save time by skipping this for autotools and clang-tidy @@ -776,6 +778,7 @@ jobs: type: 'Debug' image: 'windows-11-arm' openssh: 'OpenSSH-Windows' + tflags: '--min=1650' config: >- -DENABLE_DEBUG=ON -DCURL_USE_SCHANNEL=ON @@ -783,7 +786,7 @@ jobs: fail-fast: false steps: - - uses: msys2/setup-msys2@fb197b72ce45fb24f17bf3f807a388985654d1f2 # v2.29.0 + - uses: msys2/setup-msys2@4f806de0a5a7294ffabaff804b38a9b435a73bda # v2.30.0 with: msystem: ${{ matrix.arch == 'arm64' && 'clangarm64' || 'ucrt64' }} release: ${{ contains(matrix.image, 'arm') }} @@ -805,7 +808,7 @@ jobs: timeout-minutes: 45 run: vcpkg x-set-installed ${MATRIX_INSTALL_VCPKG} --triplet="${MATRIX_ARCH}-${MATRIX_PLAT}" - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: persist-credentials: false @@ -910,7 +913,7 @@ jobs: - name: 'curl -V' timeout-minutes: 1 run: | - /usr/bin/find . \( -name '*.exe' -o -name '*.dll' -o -name '*.lib' -o -name '*.pdb' \) -exec file '{}' \; + /usr/bin/find . \( -name '*.exe' -o -name '*.dll' -o -name '*.lib' -o -name '*.pdb' \) -exec file -- '{}' \; if [ "${MATRIX_PLAT}" != 'uwp' ]; then # Missing: ucrtbased.dll, VCRUNTIME140D.dll, VCRUNTIME140D_APP.dll PATH="$PWD/bld/lib/${MATRIX_TYPE}:$PATH" "bld/src/${MATRIX_TYPE}/curl.exe" --disable --version @@ -944,7 +947,6 @@ jobs: if [ "${MATRIX_IMAGE}" != 'windows-11-arm' ]; then # save 30-60 seconds, to counteract the slower test run step python3 -m pip --disable-pip-version-check --no-input --no-cache-dir install --progress-bar off --prefer-binary -r tests/requirements.txt fi - perl --version | tee "$GITHUB_WORKSPACE"/perlversion - name: 'run tests' if: ${{ matrix.tflags != 'skipall' && matrix.tflags != 'skiprun' }} diff --git a/.mailmap b/.mailmap index e89e3860561e..d04408efa2ea 100644 --- a/.mailmap +++ b/.mailmap @@ -1,3 +1,7 @@ +# Copyright (C) Daniel Stenberg, , et al. +# +# SPDX-License-Identifier: curl + Guenter Knauf Gisle Vanem Gisle Vanem diff --git a/CMake/CMakeConfigurableFile.in b/CMake/CMakeConfigurableFile.in deleted file mode 100644 index a3d2bc4a285f..000000000000 --- a/CMake/CMakeConfigurableFile.in +++ /dev/null @@ -1,24 +0,0 @@ -#*************************************************************************** -# _ _ ____ _ -# Project ___| | | | _ \| | -# / __| | | | |_) | | -# | (__| |_| | _ <| |___ -# \___|\___/|_| \_\_____| -# -# Copyright (C) Daniel Stenberg, , et al. -# -# This software is licensed as described in the file COPYING, which -# you should have received as part of this distribution. The terms -# are also available at https://curl.se/docs/copyright.html. -# -# You may opt to use, copy, modify, merge, publish, distribute and/or sell -# copies of the Software, and permit persons to whom the Software is -# furnished to do so, under the terms of the COPYING file. -# -# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY -# KIND, either express or implied. -# -# SPDX-License-Identifier: curl -# -########################################################################### -@CMAKE_CONFIGURABLE_FILE_CONTENT@ diff --git a/CMake/CurlSymbolHiding.cmake b/CMake/CurlSymbolHiding.cmake index 217c8832c9ab..2576a1aff36f 100644 --- a/CMake/CurlSymbolHiding.cmake +++ b/CMake/CurlSymbolHiding.cmake @@ -29,7 +29,7 @@ if(WIN32 AND (ENABLE_DEBUG OR ENABLE_CURLDEBUG)) # e.g. curl_easy_perform_ev() or curl_dbg_*(), # so disable symbol hiding for debug builds and for memory tracking. set(CURL_HIDDEN_SYMBOLS OFF) -elseif(DOS OR AMIGA OR MINGW32CE) +elseif(DOS OR AMIGA) set(CURL_HIDDEN_SYMBOLS OFF) endif() diff --git a/CMake/CurlTests.c b/CMake/CurlTests.c index 40fa50fe83dc..a06c7701f57b 100644 --- a/CMake/CurlTests.c +++ b/CMake/CurlTests.c @@ -29,7 +29,7 @@ #include /* */ #if defined(sun) || defined(__sun__) || \ - defined(__SUNPRO_C) || defined(__SUNPRO_CC) + defined(__SUNPRO_C) || defined(__SUNPRO_CC) # if defined(__SVR4) || defined(__srv4__) # define PLATFORM_SOLARIS # else @@ -119,7 +119,10 @@ int main(void) #include #include #include -int main(void) { return 0; } +int main(void) +{ + return 0; +} #endif #ifdef HAVE_FILE_OFFSET_BITS @@ -128,7 +131,7 @@ int main(void) { return 0; } We cannot simply define LARGE_OFF_T to be 9223372036854775807, since some C++ compilers masquerading as C compilers incorrectly reject 9223372036854775807. */ -#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) +#define LARGE_OFF_T (((off_t)1 << 62) - 1 + ((off_t)1 << 62)) static int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? 1 : -1]; @@ -272,7 +275,10 @@ int main(void) #include #include -static void check(char c) { (void)c; } +static void check(char c) +{ + (void)c; +} int main(void) { @@ -289,7 +295,10 @@ int main(void) #include /* Float, because a pointer cannot be implicitly cast to float */ -static void check(float f) { (void)f; } +static void check(float f) +{ + (void)f; +} int main(void) { diff --git a/CMake/FindBrotli.cmake b/CMake/FindBrotli.cmake index 690b5a9c27ce..981b30cafd57 100644 --- a/CMake/FindBrotli.cmake +++ b/CMake/FindBrotli.cmake @@ -25,35 +25,31 @@ # # Input variables: # -# - `BROTLI_INCLUDE_DIR`: The brotli include directory. -# - `BROTLICOMMON_LIBRARY`: Path to `brotlicommon` library. -# - `BROTLIDEC_LIBRARY`: Path to `brotlidec` library. +# - `BROTLI_INCLUDE_DIR`: Absolute path to brotli include directory. +# - `BROTLICOMMON_LIBRARY`: Absolute path to `brotlicommon` library. +# - `BROTLIDEC_LIBRARY`: Absolute path to `brotlidec` library. # -# Result variables: +# Defines: # # - `BROTLI_FOUND`: System has brotli. -# - `BROTLI_INCLUDE_DIRS`: The brotli include directories. -# - `BROTLI_LIBRARIES`: The brotli library names. -# - `BROTLI_LIBRARY_DIRS`: The brotli library directories. -# - `BROTLI_PC_REQUIRES`: The brotli pkg-config packages. -# - `BROTLI_CFLAGS`: Required compiler flags. # - `BROTLI_VERSION`: Version of brotli. +# - `CURL::brotli`: brotli library target. -set(BROTLI_PC_REQUIRES "libbrotlidec" "libbrotlicommon") # order is significant: brotlidec then brotlicommon +set(_brotli_pc_requires "libbrotlidec" "libbrotlicommon") # order is significant: brotlidec then brotlicommon if(CURL_USE_PKGCONFIG AND NOT DEFINED BROTLI_INCLUDE_DIR AND NOT DEFINED BROTLICOMMON_LIBRARY AND NOT DEFINED BROTLIDEC_LIBRARY) find_package(PkgConfig QUIET) - pkg_check_modules(BROTLI ${BROTLI_PC_REQUIRES}) + pkg_check_modules(_brotli ${_brotli_pc_requires}) endif() -if(BROTLI_FOUND) +if(_brotli_FOUND) set(Brotli_FOUND TRUE) - set(BROTLI_VERSION "${BROTLI_libbrotlicommon_VERSION}") - string(REPLACE ";" " " BROTLI_CFLAGS "${BROTLI_CFLAGS}") - message(STATUS "Found Brotli (via pkg-config): ${BROTLI_INCLUDE_DIRS} (found version \"${BROTLI_VERSION}\")") + set(BROTLI_FOUND TRUE) + set(BROTLI_VERSION ${_brotli_libbrotlicommon_VERSION}) + message(STATUS "Found Brotli (via pkg-config): ${_brotli_INCLUDE_DIRS} (found version \"${BROTLI_VERSION}\")") else() find_path(BROTLI_INCLUDE_DIR "brotli/decode.h") find_library(BROTLICOMMON_LIBRARY NAMES "brotlicommon") @@ -68,9 +64,25 @@ else() ) if(BROTLI_FOUND) - set(BROTLI_INCLUDE_DIRS ${BROTLI_INCLUDE_DIR}) - set(BROTLI_LIBRARIES ${BROTLIDEC_LIBRARY} ${BROTLICOMMON_LIBRARY}) + set(_brotli_INCLUDE_DIRS ${BROTLI_INCLUDE_DIR}) + set(_brotli_LIBRARIES ${BROTLIDEC_LIBRARY} ${BROTLICOMMON_LIBRARY}) endif() mark_as_advanced(BROTLI_INCLUDE_DIR BROTLIDEC_LIBRARY BROTLICOMMON_LIBRARY) endif() + +if(BROTLI_FOUND) + if(CMAKE_VERSION VERSION_LESS 3.13) + link_directories(${_brotli_LIBRARY_DIRS}) + endif() + + if(NOT TARGET CURL::brotli) + add_library(CURL::brotli INTERFACE IMPORTED) + set_target_properties(CURL::brotli PROPERTIES + INTERFACE_LIBCURL_PC_MODULES "${_brotli_pc_requires}" + INTERFACE_COMPILE_OPTIONS "${_brotli_CFLAGS}" + INTERFACE_INCLUDE_DIRECTORIES "${_brotli_INCLUDE_DIRS}" + INTERFACE_LINK_DIRECTORIES "${_brotli_LIBRARY_DIRS}" + INTERFACE_LINK_LIBRARIES "${_brotli_LIBRARIES}") + endif() +endif() diff --git a/CMake/FindCares.cmake b/CMake/FindCares.cmake index cc47e2d33103..4a20bc0af471 100644 --- a/CMake/FindCares.cmake +++ b/CMake/FindCares.cmake @@ -25,32 +25,29 @@ # # Input variables: # -# - `CARES_INCLUDE_DIR`: The c-ares include directory. -# - `CARES_LIBRARY`: Path to `cares` library. +# - `CARES_INCLUDE_DIR`: Absolute path to c-ares include directory. +# - `CARES_LIBRARY`: Absolute path to `cares` library. # -# Result variables: +# Defines: # -# - `CARES_FOUND`: System has c-ares. -# - `CARES_INCLUDE_DIRS`: The c-ares include directories. -# - `CARES_LIBRARIES`: The c-ares library names. -# - `CARES_LIBRARY_DIRS`: The c-ares library directories. -# - `CARES_PC_REQUIRES`: The c-ares pkg-config packages. -# - `CARES_CFLAGS`: Required compiler flags. -# - `CARES_VERSION`: Version of c-ares. +# - `CARES_FOUND`: System has c-ares. +# - `CARES_VERSION`: Version of c-ares. +# - `CURL::cares`: c-ares library target. -set(CARES_PC_REQUIRES "libcares") +set(_cares_pc_requires "libcares") if(CURL_USE_PKGCONFIG AND NOT DEFINED CARES_INCLUDE_DIR AND NOT DEFINED CARES_LIBRARY) find_package(PkgConfig QUIET) - pkg_check_modules(CARES ${CARES_PC_REQUIRES}) + pkg_check_modules(_cares ${_cares_pc_requires}) endif() -if(CARES_FOUND) +if(_cares_FOUND) set(Cares_FOUND TRUE) - string(REPLACE ";" " " CARES_CFLAGS "${CARES_CFLAGS}") - message(STATUS "Found Cares (via pkg-config): ${CARES_INCLUDE_DIRS} (found version \"${CARES_VERSION}\")") + set(CARES_FOUND TRUE) + set(CARES_VERSION ${_cares_VERSION}) + message(STATUS "Found Cares (via pkg-config): ${_cares_INCLUDE_DIRS} (found version \"${CARES_VERSION}\")") else() find_path(CARES_INCLUDE_DIR NAMES "ares.h") find_library(CARES_LIBRARY NAMES ${CARES_NAMES} "cares") @@ -85,13 +82,29 @@ else() ) if(CARES_FOUND) - set(CARES_INCLUDE_DIRS ${CARES_INCLUDE_DIR}) - set(CARES_LIBRARIES ${CARES_LIBRARY}) + set(_cares_INCLUDE_DIRS ${CARES_INCLUDE_DIR}) + set(_cares_LIBRARIES ${CARES_LIBRARY}) endif() mark_as_advanced(CARES_INCLUDE_DIR CARES_LIBRARY) endif() -if(CARES_FOUND AND WIN32) - list(APPEND CARES_LIBRARIES "iphlpapi") # for if_indextoname and others +if(CARES_FOUND) + if(WIN32) + list(APPEND _cares_LIBRARIES "iphlpapi") # for if_indextoname and others + endif() + + if(CMAKE_VERSION VERSION_LESS 3.13) + link_directories(${_cares_LIBRARY_DIRS}) + endif() + + if(NOT TARGET CURL::cares) + add_library(CURL::cares INTERFACE IMPORTED) + set_target_properties(CURL::cares PROPERTIES + INTERFACE_LIBCURL_PC_MODULES "${_cares_pc_requires}" + INTERFACE_COMPILE_OPTIONS "${_cares_CFLAGS}" + INTERFACE_INCLUDE_DIRECTORIES "${_cares_INCLUDE_DIRS}" + INTERFACE_LINK_DIRECTORIES "${_cares_LIBRARY_DIRS}" + INTERFACE_LINK_LIBRARIES "${_cares_LIBRARIES}") + endif() endif() diff --git a/CMake/FindGSS.cmake b/CMake/FindGSS.cmake index 1661f208d2f8..106c4c4edd71 100644 --- a/CMake/FindGSS.cmake +++ b/CMake/FindGSS.cmake @@ -25,19 +25,15 @@ # # Input variables: # -# - `GSS_ROOT_DIR`: Set this variable to the root installation of GSS. (also supported as environment) +# - `GSS_ROOT_DIR`: Absolute path to the root installation of GSS. (also supported as environment) # -# Result variables: +# Defines: # -# - `GSS_FOUND`: System has a GSS library. -# - `GSS_FLAVOUR`: "GNU" or "MIT" if anything found. -# - `GSS_INCLUDE_DIRS`: The GSS include directories. -# - `GSS_LIBRARIES`: The GSS library names. -# - `GSS_LIBRARY_DIRS`: The GSS library directories. -# - `GSS_PC_REQUIRES`: The GSS pkg-config packages. -# - `GSS_CFLAGS`: Required compiler flags. -# - `GSS_VERSION`: This is set to version advertised by pkg-config or read from manifest. -# In case the library is found but no version info available it is set to "unknown" +# - `GSS_FOUND`: System has a GSS library. +# - `GSS_VERSION`: This is set to version advertised by pkg-config or read from manifest. +# In case the library is found but no version info available it is set to "unknown" +# - `CURL::gss`: GSS library target. +# - CURL_GSS_FLAVOUR`: Custom property. "GNU" or "MIT" if detected. set(_gnu_modname "gss") set(_mit_modname "mit-krb5-gssapi") @@ -140,7 +136,7 @@ if(NOT _gss_FOUND) # Not found by pkg-config. Let us take more traditional appr # Older versions may not have the "--vendor" parameter. In this case we just do not care. if(NOT _gss_configure_failed AND NOT _gss_vendor MATCHES "Heimdal|heimdal") - set(GSS_FLAVOUR "MIT") # assume a default, should not really matter + set(_gss_flavour "MIT") # assume a default, should not really matter endif() else() # Either there is no config script or we are on a platform that does not provide one (Windows?) @@ -156,7 +152,7 @@ if(NOT _gss_FOUND) # Not found by pkg-config. Let us take more traditional appr cmake_pop_check_state() if(_gss_have_mit_headers) - set(GSS_FLAVOUR "MIT") + set(_gss_flavour "MIT") if(WIN32) if(CMAKE_SIZEOF_VOID_P EQUAL 8) list(APPEND _gss_libdir_suffixes "lib/AMD64") @@ -174,14 +170,14 @@ if(NOT _gss_FOUND) # Not found by pkg-config. Let us take more traditional appr find_path(_gss_INCLUDE_DIRS NAMES "gss.h" HINTS ${_gss_root_hints} PATH_SUFFIXES "include") if(_gss_INCLUDE_DIRS) - set(GSS_FLAVOUR "GNU") - set(GSS_PC_REQUIRES ${_gnu_modname}) + set(_gss_flavour "GNU") + set(_gss_pc_requires ${_gnu_modname}) set(_gss_libname "gss") endif() endif() # If we have headers, look up libraries - if(GSS_FLAVOUR) + if(_gss_flavour) set(_gss_libdir_hints ${_gss_root_hints}) if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.20) cmake_path(GET _gss_INCLUDE_DIRS PARENT_PATH _gss_calculated_potential_root) @@ -193,34 +189,28 @@ if(NOT _gss_FOUND) # Not found by pkg-config. Let us take more traditional appr find_library(_gss_LIBRARIES NAMES ${_gss_libname} HINTS ${_gss_libdir_hints} PATH_SUFFIXES ${_gss_libdir_suffixes}) endif() endif() - if(NOT GSS_FLAVOUR) + if(NOT _gss_flavour) message(FATAL_ERROR "GNU or MIT GSS is required") endif() else() # _gss_MODULE_NAME set since CMake 3.16. # _pkg_check_modules_pkg_name is undocumented and used as a fallback for CMake <3.16 versions. if(_gss_MODULE_NAME STREQUAL _gnu_modname OR _pkg_check_modules_pkg_name STREQUAL _gnu_modname) - set(GSS_FLAVOUR "GNU") - set(GSS_PC_REQUIRES ${_gnu_modname}) + set(_gss_flavour "GNU") + set(_gss_pc_requires ${_gnu_modname}) elseif(_gss_MODULE_NAME STREQUAL _mit_modname OR _pkg_check_modules_pkg_name STREQUAL _mit_modname) - set(GSS_FLAVOUR "MIT") - set(GSS_PC_REQUIRES ${_mit_modname}) + set(_gss_flavour "MIT") + set(_gss_pc_requires ${_mit_modname}) else() message(FATAL_ERROR "GNU or MIT GSS is required") endif() - message(STATUS "Found GSS/${GSS_FLAVOUR} (via pkg-config): ${_gss_INCLUDE_DIRS} (found version \"${_gss_version}\")") + message(STATUS "Found GSS/${_gss_flavour} (via pkg-config): ${_gss_INCLUDE_DIRS} (found version \"${_gss_version}\")") endif() -string(REPLACE ";" " " _gss_CFLAGS "${_gss_CFLAGS}") - -set(GSS_INCLUDE_DIRS ${_gss_INCLUDE_DIRS}) -set(GSS_LIBRARIES ${_gss_LIBRARIES}) -set(GSS_LIBRARY_DIRS ${_gss_LIBRARY_DIRS}) -set(GSS_CFLAGS ${_gss_CFLAGS}) set(GSS_VERSION ${_gss_version}) if(NOT GSS_VERSION) - if(GSS_FLAVOUR STREQUAL "MIT") + if(_gss_flavour STREQUAL "MIT") if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.24) cmake_host_system_information(RESULT _mit_version QUERY WINDOWS_REGISTRY "HKLM/SOFTWARE/MIT/Kerberos/SDK/CurrentVersion" VALUE "VersionString") @@ -234,9 +224,9 @@ if(NOT GSS_VERSION) set(GSS_VERSION "MIT Unknown") endif() else() # GNU - if(GSS_INCLUDE_DIRS AND EXISTS "${GSS_INCLUDE_DIRS}/gss.h") + if(_gss_INCLUDE_DIRS AND EXISTS "${_gss_INCLUDE_DIRS}/gss.h") set(_version_regex "#[\t ]*define[\t ]+GSS_VERSION[\t ]+\"([^\"]*)\"") - file(STRINGS "${GSS_INCLUDE_DIRS}/gss.h" _version_str REGEX "${_version_regex}") + file(STRINGS "${_gss_INCLUDE_DIRS}/gss.h" _version_str REGEX "${_version_regex}") string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}") set(GSS_VERSION "${_version_str}") unset(_version_regex) @@ -248,12 +238,12 @@ endif() include(FindPackageHandleStandardArgs) find_package_handle_standard_args(GSS REQUIRED_VARS - GSS_FLAVOUR - GSS_LIBRARIES + _gss_flavour + _gss_LIBRARIES VERSION_VAR GSS_VERSION FAIL_MESSAGE - "Could NOT find GSS, try to set the path to GSS root folder in the system variable GSS_ROOT_DIR" + "Could NOT find GSS, try to set the absolute path to GSS installation root directory in the environment variable GSS_ROOT_DIR" ) mark_as_advanced( @@ -266,3 +256,20 @@ mark_as_advanced( _gss_PREFIX _gss_version ) + +if(GSS_FOUND) + if(CMAKE_VERSION VERSION_LESS 3.13) + link_directories(${_gss_LIBRARY_DIRS}) + endif() + + if(NOT TARGET CURL::gss) + add_library(CURL::gss INTERFACE IMPORTED) + set_target_properties(CURL::gss PROPERTIES + INTERFACE_CURL_GSS_FLAVOUR "${_gss_flavour}" + INTERFACE_LIBCURL_PC_MODULES "${_gss_pc_requires}" + INTERFACE_COMPILE_OPTIONS "${_gss_CFLAGS}" + INTERFACE_INCLUDE_DIRECTORIES "${_gss_INCLUDE_DIRS}" + INTERFACE_LINK_DIRECTORIES "${_gss_LIBRARY_DIRS}" + INTERFACE_LINK_LIBRARIES "${_gss_LIBRARIES}") + endif() +endif() diff --git a/CMake/FindGnuTLS.cmake b/CMake/FindGnuTLS.cmake new file mode 100644 index 000000000000..fff57b2c293a --- /dev/null +++ b/CMake/FindGnuTLS.cmake @@ -0,0 +1,96 @@ +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) Daniel Stenberg, , et al. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +# SPDX-License-Identifier: curl +# +########################################################################### +# Find the GnuTLS library +# +# Input variables: +# +# - `GNUTLS_INCLUDE_DIR`: Absolute path to GnuTLS include directory. +# - `GNUTLS_LIBRARY`: Absolute path to `gnutls` library. +# +# Defines: +# +# - `GNUTLS_FOUND`: System has GnuTLS. +# - `GNUTLS_VERSION`: Version of GnuTLS. +# - `CURL::gnutls`: GnuTLS library target. + +set(_gnutls_pc_requires "gnutls") + +if(CURL_USE_PKGCONFIG AND + NOT DEFINED GNUTLS_INCLUDE_DIR AND + NOT DEFINED GNUTLS_LIBRARY) + find_package(PkgConfig QUIET) + pkg_check_modules(_gnutls ${_gnutls_pc_requires}) +endif() + +if(_gnutls_FOUND) + set(GnuTLS_FOUND TRUE) + set(GNUTLS_FOUND TRUE) + set(GNUTLS_VERSION ${_gnutls_VERSION}) + message(STATUS "Found GnuTLS (via pkg-config): ${_gnutls_INCLUDE_DIRS} (found version \"${GNUTLS_VERSION}\")") +else() + find_path(GNUTLS_INCLUDE_DIR NAMES "gnutls/gnutls.h") + find_library(GNUTLS_LIBRARY NAMES "gnutls" "libgnutls") + + unset(GNUTLS_VERSION CACHE) + if(GNUTLS_INCLUDE_DIR AND EXISTS "${GNUTLS_INCLUDE_DIR}/gnutls/gnutls.h") + set(_version_regex "#[\t ]*define[\t ]+GNUTLS_VERSION[\t ]+\"([^\"]*)\"") + file(STRINGS "${GNUTLS_INCLUDE_DIR}/gnutls/gnutls.h" _version_str REGEX "${_version_regex}") + string(REGEX REPLACE "${_version_regex}" "\\1" _version_str "${_version_str}") + set(GNUTLS_VERSION "${_version_str}") + unset(_version_regex) + unset(_version_str) + endif() + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(GnuTLS + REQUIRED_VARS + GNUTLS_INCLUDE_DIR + GNUTLS_LIBRARY + VERSION_VAR + GNUTLS_VERSION + ) + + if(GNUTLS_FOUND) + set(_gnutls_INCLUDE_DIRS ${GNUTLS_INCLUDE_DIR}) + set(_gnutls_LIBRARIES ${GNUTLS_LIBRARY}) + endif() + + mark_as_advanced(GNUTLS_INCLUDE_DIR GNUTLS_LIBRARY) +endif() + +if(GNUTLS_FOUND) + if(CMAKE_VERSION VERSION_LESS 3.13) + link_directories(${_gnutls_LIBRARY_DIRS}) + endif() + + if(NOT TARGET CURL::gnutls) + add_library(CURL::gnutls INTERFACE IMPORTED) + set_target_properties(CURL::gnutls PROPERTIES + INTERFACE_LIBCURL_PC_MODULES "${_gnutls_pc_requires}" + INTERFACE_COMPILE_OPTIONS "${_gnutls_CFLAGS}" + INTERFACE_INCLUDE_DIRECTORIES "${_gnutls_INCLUDE_DIRS}" + INTERFACE_LINK_DIRECTORIES "${_gnutls_LIBRARY_DIRS}" + INTERFACE_LINK_LIBRARIES "${_gnutls_LIBRARIES}") + endif() +endif() diff --git a/CMake/FindLDAP.cmake b/CMake/FindLDAP.cmake index fdc6d7be943d..2f5cc713c72d 100644 --- a/CMake/FindLDAP.cmake +++ b/CMake/FindLDAP.cmake @@ -25,36 +25,32 @@ # # Input variables: # -# - `LDAP_INCLUDE_DIR`: The ldap include directory. -# - `LDAP_LIBRARY`: Path to `ldap` library. -# - `LDAP_LBER_LIBRARY`: Path to `lber` library. +# - `LDAP_INCLUDE_DIR`: Absolute path to ldap include directory. +# - `LDAP_LIBRARY`: Absolute path to `ldap` library. +# - `LDAP_LBER_LIBRARY`: Absolute path to `lber` library. # -# Result variables: +# Defines: # # - `LDAP_FOUND`: System has ldap. -# - `LDAP_INCLUDE_DIRS`: The ldap include directories. -# - `LDAP_LIBRARIES`: The ldap library names. -# - `LDAP_LIBRARY_DIRS`: The ldap library directories. -# - `LDAP_PC_REQUIRES`: The ldap pkg-config packages. -# - `LDAP_CFLAGS`: Required compiler flags. # - `LDAP_VERSION`: Version of ldap. +# - `CURL::ldap`: ldap library target. -set(LDAP_PC_REQUIRES "ldap" "lber") +set(_ldap_pc_requires "ldap" "lber") if(CURL_USE_PKGCONFIG AND NOT DEFINED LDAP_INCLUDE_DIR AND NOT DEFINED LDAP_LIBRARY AND NOT DEFINED LDAP_LBER_LIBRARY) find_package(PkgConfig QUIET) - pkg_check_modules(LDAP ${LDAP_PC_REQUIRES}) + pkg_check_modules(_ldap ${_ldap_pc_requires}) endif() -if(LDAP_FOUND) - set(LDAP_VERSION "${LDAP_ldap_VERSION}") - string(REPLACE ";" " " LDAP_CFLAGS "${LDAP_CFLAGS}") - message(STATUS "Found LDAP (via pkg-config): ${LDAP_INCLUDE_DIRS} (found version \"${LDAP_VERSION}\")") +if(_ldap_FOUND) + set(LDAP_FOUND TRUE) + set(LDAP_VERSION ${_ldap_ldap_VERSION}) + message(STATUS "Found LDAP (via pkg-config): ${_ldap_INCLUDE_DIRS} (found version \"${LDAP_VERSION}\")") else() - set(LDAP_PC_REQUIRES "") # Depend on pkg-config only when found via pkg-config + set(_ldap_pc_requires "") # Depend on pkg-config only when found via pkg-config # On Apple the SDK LDAP gets picked up from # 'MacOSX.sdk/System/Library/Frameworks/LDAP.framework/Headers', which contains @@ -99,9 +95,25 @@ else() ) if(LDAP_FOUND) - set(LDAP_INCLUDE_DIRS ${LDAP_INCLUDE_DIR}) - set(LDAP_LIBRARIES ${LDAP_LIBRARY} ${LDAP_LBER_LIBRARY}) + set(_ldap_INCLUDE_DIRS ${LDAP_INCLUDE_DIR}) + set(_ldap_LIBRARIES ${LDAP_LIBRARY} ${LDAP_LBER_LIBRARY}) endif() mark_as_advanced(LDAP_INCLUDE_DIR LDAP_LIBRARY LDAP_LBER_LIBRARY) endif() + +if(LDAP_FOUND) + if(CMAKE_VERSION VERSION_LESS 3.13) + link_directories(${_ldap_LIBRARY_DIRS}) + endif() + + if(NOT TARGET CURL::ldap) + add_library(CURL::ldap INTERFACE IMPORTED) + set_target_properties(CURL::ldap PROPERTIES + INTERFACE_LIBCURL_PC_MODULES "${_ldap_pc_requires}" + INTERFACE_COMPILE_OPTIONS "${_ldap_CFLAGS}" + INTERFACE_INCLUDE_DIRECTORIES "${_ldap_INCLUDE_DIRS}" + INTERFACE_LINK_DIRECTORIES "${_ldap_LIBRARY_DIRS}" + INTERFACE_LINK_LIBRARIES "${_ldap_LIBRARIES}") + endif() +endif() diff --git a/CMake/FindLibbacktrace.cmake b/CMake/FindLibbacktrace.cmake new file mode 100644 index 000000000000..c6f7b700c43c --- /dev/null +++ b/CMake/FindLibbacktrace.cmake @@ -0,0 +1,65 @@ +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) Daniel Stenberg, , et al. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +# SPDX-License-Identifier: curl +# +########################################################################### +# Find the libbacktrace library +# +# Input variables: +# +# - `LIBBACKTRACE_INCLUDE_DIR`: Absolute path to libbacktrace include directory. +# - `LIBBACKTRACE_LIBRARY`: Absolute path to `libbacktrace` library. +# +# Defines: +# +# - `LIBBACKTRACE_FOUND`: System has libbacktrace. +# - `CURL::libbacktrace`: libbacktrace library target. + +find_path(LIBBACKTRACE_INCLUDE_DIR NAMES "backtrace.h") +find_library(LIBBACKTRACE_LIBRARY NAMES "backtrace" "libbacktrace") + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Libbacktrace + REQUIRED_VARS + LIBBACKTRACE_INCLUDE_DIR + LIBBACKTRACE_LIBRARY +) + +if(LIBBACKTRACE_FOUND) + set(_libbacktrace_INCLUDE_DIRS ${LIBBACKTRACE_INCLUDE_DIR}) + set(_libbacktrace_LIBRARIES ${LIBBACKTRACE_LIBRARY}) + + if(CMAKE_VERSION VERSION_LESS 3.13) + link_directories(${_libbacktrace_LIBRARY_DIRS}) + endif() + + if(NOT TARGET CURL::libbacktrace) + add_library(CURL::libbacktrace INTERFACE IMPORTED) + set_target_properties(CURL::libbacktrace PROPERTIES + INTERFACE_LIBCURL_PC_MODULES "${_libbacktrace_pc_requires}" + INTERFACE_COMPILE_OPTIONS "${_libbacktrace_CFLAGS}" + INTERFACE_INCLUDE_DIRECTORIES "${_libbacktrace_INCLUDE_DIRS}" + INTERFACE_LINK_DIRECTORIES "${_libbacktrace_LIBRARY_DIRS}" + INTERFACE_LINK_LIBRARIES "${_libbacktrace_LIBRARIES}") + endif() +endif() + +mark_as_advanced(LIBBACKTRACE_INCLUDE_DIR LIBBACKTRACE_LIBRARY) diff --git a/CMake/FindLibgsasl.cmake b/CMake/FindLibgsasl.cmake index 878d651883da..5ddf957d72d8 100644 --- a/CMake/FindLibgsasl.cmake +++ b/CMake/FindLibgsasl.cmake @@ -25,32 +25,28 @@ # # Input variables: # -# - `LIBGSASL_INCLUDE_DIR`: The libgsasl include directory. -# - `LIBGSASL_LIBRARY`: Path to `libgsasl` library. +# - `LIBGSASL_INCLUDE_DIR`: Absolute path to libgsasl include directory. +# - `LIBGSASL_LIBRARY`: Absolute path to `libgsasl` library. # -# Result variables: +# Defines: # -# - `LIBGSASL_FOUND`: System has libgsasl. -# - `LIBGSASL_INCLUDE_DIRS`: The libgsasl include directories. -# - `LIBGSASL_LIBRARIES`: The libgsasl library names. -# - `LIBGSASL_LIBRARY_DIRS`: The libgsasl library directories. -# - `LIBGSASL_PC_REQUIRES`: The libgsasl pkg-config packages. -# - `LIBGSASL_CFLAGS`: Required compiler flags. -# - `LIBGSASL_VERSION`: Version of libgsasl. +# - `LIBGSASL_FOUND`: System has libgsasl. +# - `LIBGSASL_VERSION`: Version of libgsasl. +# - `CURL::libgsasl`: libgsasl library target. -set(LIBGSASL_PC_REQUIRES "libgsasl") +set(_libgsasl_pc_requires "libgsasl") if(CURL_USE_PKGCONFIG AND NOT DEFINED LIBGSASL_INCLUDE_DIR AND NOT DEFINED LIBGSASL_LIBRARY) find_package(PkgConfig QUIET) - pkg_check_modules(LIBGSASL ${LIBGSASL_PC_REQUIRES}) + pkg_check_modules(_libgsasl ${_libgsasl_pc_requires}) endif() -if(LIBGSASL_FOUND) +if(_libgsasl_FOUND) set(Libgsasl_FOUND TRUE) - string(REPLACE ";" " " LIBGSASL_CFLAGS "${LIBGSASL_CFLAGS}") - message(STATUS "Found Libgsasl (via pkg-config): ${LIBGSASL_INCLUDE_DIRS} (found version \"${LIBGSASL_VERSION}\")") + set(LIBGSASL_FOUND TRUE) + message(STATUS "Found Libgsasl (via pkg-config): ${_libgsasl_INCLUDE_DIRS} (found version \"${LIBGSASL_VERSION}\")") else() find_path(LIBGSASL_INCLUDE_DIR NAMES "gsasl.h") find_library(LIBGSASL_LIBRARY NAMES "gsasl" "libgsasl") @@ -75,9 +71,25 @@ else() ) if(LIBGSASL_FOUND) - set(LIBGSASL_INCLUDE_DIRS ${LIBGSASL_INCLUDE_DIR}) - set(LIBGSASL_LIBRARIES ${LIBGSASL_LIBRARY}) + set(_libgsasl_INCLUDE_DIRS ${LIBGSASL_INCLUDE_DIR}) + set(_libgsasl_LIBRARIES ${LIBGSASL_LIBRARY}) endif() mark_as_advanced(LIBGSASL_INCLUDE_DIR LIBGSASL_LIBRARY) endif() + +if(LIBGSASL_FOUND) + if(CMAKE_VERSION VERSION_LESS 3.13) + link_directories(${_libgsasl_LIBRARY_DIRS}) + endif() + + if(NOT TARGET CURL::libgsasl) + add_library(CURL::libgsasl INTERFACE IMPORTED) + set_target_properties(CURL::libgsasl PROPERTIES + INTERFACE_LIBCURL_PC_MODULES "${_libgsasl_pc_requires}" + INTERFACE_COMPILE_OPTIONS "${_libgsasl_CFLAGS}" + INTERFACE_INCLUDE_DIRECTORIES "${_libgsasl_INCLUDE_DIRS}" + INTERFACE_LINK_DIRECTORIES "${_libgsasl_LIBRARY_DIRS}" + INTERFACE_LINK_LIBRARIES "${_libgsasl_LIBRARIES}") + endif() +endif() diff --git a/CMake/FindLibidn2.cmake b/CMake/FindLibidn2.cmake index f8f00f0c7913..336a7f7b404e 100644 --- a/CMake/FindLibidn2.cmake +++ b/CMake/FindLibidn2.cmake @@ -25,32 +25,29 @@ # # Input variables: # -# - `LIBIDN2_INCLUDE_DIR`: The libidn2 include directory. -# - `LIBIDN2_LIBRARY`: Path to `libidn2` library. +# - `LIBIDN2_INCLUDE_DIR`: Absolute path to libidn2 include directory. +# - `LIBIDN2_LIBRARY`: Absolute path to `libidn2` library. # -# Result variables: +# Defines: # -# - `LIBIDN2_FOUND`: System has libidn2. -# - `LIBIDN2_INCLUDE_DIRS`: The libidn2 include directories. -# - `LIBIDN2_LIBRARIES`: The libidn2 library names. -# - `LIBIDN2_LIBRARY_DIRS`: The libidn2 library directories. -# - `LIBIDN2_PC_REQUIRES`: The libidn2 pkg-config packages. -# - `LIBIDN2_CFLAGS`: Required compiler flags. -# - `LIBIDN2_VERSION`: Version of libidn2. +# - `LIBIDN2_FOUND`: System has libidn2. +# - `LIBIDN2_VERSION`: Version of libidn2. +# - `CURL::libidn2`: libidn2 library target. -set(LIBIDN2_PC_REQUIRES "libidn2") +set(_libidn2_pc_requires "libidn2") if(CURL_USE_PKGCONFIG AND NOT DEFINED LIBIDN2_INCLUDE_DIR AND NOT DEFINED LIBIDN2_LIBRARY) find_package(PkgConfig QUIET) - pkg_check_modules(LIBIDN2 ${LIBIDN2_PC_REQUIRES}) + pkg_check_modules(_libidn2 ${_libidn2_pc_requires}) endif() -if(LIBIDN2_FOUND) +if(_libidn2_FOUND) set(Libidn2_FOUND TRUE) - string(REPLACE ";" " " LIBIDN2_CFLAGS "${LIBIDN2_CFLAGS}") - message(STATUS "Found Libidn2 (via pkg-config): ${LIBIDN2_INCLUDE_DIRS} (found version \"${LIBIDN2_VERSION}\")") + set(LIBIDN2_FOUND TRUE) + set(LIBIDN2_VERSION ${_libidn2_VERSION}) + message(STATUS "Found Libidn2 (via pkg-config): ${_libidn2_INCLUDE_DIRS} (found version \"${LIBIDN2_VERSION}\")") else() find_path(LIBIDN2_INCLUDE_DIR NAMES "idn2.h") find_library(LIBIDN2_LIBRARY NAMES "idn2" "libidn2") @@ -75,9 +72,25 @@ else() ) if(LIBIDN2_FOUND) - set(LIBIDN2_INCLUDE_DIRS ${LIBIDN2_INCLUDE_DIR}) - set(LIBIDN2_LIBRARIES ${LIBIDN2_LIBRARY}) + set(_libidn2_INCLUDE_DIRS ${LIBIDN2_INCLUDE_DIR}) + set(_libidn2_LIBRARIES ${LIBIDN2_LIBRARY}) endif() mark_as_advanced(LIBIDN2_INCLUDE_DIR LIBIDN2_LIBRARY) endif() + +if(LIBIDN2_FOUND) + if(CMAKE_VERSION VERSION_LESS 3.13) + link_directories(${_libidn2_LIBRARY_DIRS}) + endif() + + if(NOT TARGET CURL::libidn2) + add_library(CURL::libidn2 INTERFACE IMPORTED) + set_target_properties(CURL::libidn2 PROPERTIES + INTERFACE_LIBCURL_PC_MODULES "${_libidn2_pc_requires}" + INTERFACE_COMPILE_OPTIONS "${_libidn2_CFLAGS}" + INTERFACE_INCLUDE_DIRECTORIES "${_libidn2_INCLUDE_DIRS}" + INTERFACE_LINK_DIRECTORIES "${_libidn2_LIBRARY_DIRS}" + INTERFACE_LINK_LIBRARIES "${_libidn2_LIBRARIES}") + endif() +endif() diff --git a/CMake/FindLibpsl.cmake b/CMake/FindLibpsl.cmake index d6fde4b2d03c..9b1a0cdd97b4 100644 --- a/CMake/FindLibpsl.cmake +++ b/CMake/FindLibpsl.cmake @@ -25,32 +25,29 @@ # # Input variables: # -# - `LIBPSL_INCLUDE_DIR`: The libpsl include directory. -# - `LIBPSL_LIBRARY`: Path to `libpsl` library. +# - `LIBPSL_INCLUDE_DIR`: Absolute path to libpsl include directory. +# - `LIBPSL_LIBRARY`: Absolute path to `libpsl` library. # -# Result variables: +# Defines: # -# - `LIBPSL_FOUND`: System has libpsl. -# - `LIBPSL_INCLUDE_DIRS`: The libpsl include directories. -# - `LIBPSL_LIBRARIES`: The libpsl library names. -# - `LIBPSL_LIBRARY_DIRS`: The libpsl library directories. -# - `LIBPSL_PC_REQUIRES`: The libpsl pkg-config packages. -# - `LIBPSL_CFLAGS`: Required compiler flags. -# - `LIBPSL_VERSION`: Version of libpsl. +# - `LIBPSL_FOUND`: System has libpsl. +# - `LIBPSL_VERSION`: Version of libpsl. +# - `CURL::libpsl`: libpsl library target. -set(LIBPSL_PC_REQUIRES "libpsl") +set(_libpsl_pc_requires "libpsl") if(CURL_USE_PKGCONFIG AND NOT DEFINED LIBPSL_INCLUDE_DIR AND NOT DEFINED LIBPSL_LIBRARY) find_package(PkgConfig QUIET) - pkg_check_modules(LIBPSL ${LIBPSL_PC_REQUIRES}) + pkg_check_modules(_libpsl ${_libpsl_pc_requires}) endif() -if(LIBPSL_FOUND AND LIBPSL_INCLUDE_DIRS) +if(_libpsl_FOUND AND _libpsl_INCLUDE_DIRS) set(Libpsl_FOUND TRUE) - string(REPLACE ";" " " LIBPSL_CFLAGS "${LIBPSL_CFLAGS}") - message(STATUS "Found Libpsl (via pkg-config): ${LIBPSL_INCLUDE_DIRS} (found version \"${LIBPSL_VERSION}\")") + set(LIBPSL_FOUND TRUE) + set(LIBPSL_VERSION ${_libpsl_VERSION}) + message(STATUS "Found Libpsl (via pkg-config): ${_libpsl_INCLUDE_DIRS} (found version \"${LIBPSL_VERSION}\")") else() find_path(LIBPSL_INCLUDE_DIR NAMES "libpsl.h") find_library(LIBPSL_LIBRARY NAMES "psl" "libpsl") @@ -75,9 +72,25 @@ else() ) if(LIBPSL_FOUND) - set(LIBPSL_INCLUDE_DIRS ${LIBPSL_INCLUDE_DIR}) - set(LIBPSL_LIBRARIES ${LIBPSL_LIBRARY}) + set(_libpsl_INCLUDE_DIRS ${LIBPSL_INCLUDE_DIR}) + set(_libpsl_LIBRARIES ${LIBPSL_LIBRARY}) endif() mark_as_advanced(LIBPSL_INCLUDE_DIR LIBPSL_LIBRARY) endif() + +if(LIBPSL_FOUND) + if(CMAKE_VERSION VERSION_LESS 3.13) + link_directories(${_libpsl_LIBRARY_DIRS}) + endif() + + if(NOT TARGET CURL::libpsl) + add_library(CURL::libpsl INTERFACE IMPORTED) + set_target_properties(CURL::libpsl PROPERTIES + INTERFACE_LIBCURL_PC_MODULES "${_libpsl_pc_requires}" + INTERFACE_COMPILE_OPTIONS "${_libpsl_CFLAGS}" + INTERFACE_INCLUDE_DIRECTORIES "${_libpsl_INCLUDE_DIRS}" + INTERFACE_LINK_DIRECTORIES "${_libpsl_LIBRARY_DIRS}" + INTERFACE_LINK_LIBRARIES "${_libpsl_LIBRARIES}") + endif() +endif() diff --git a/CMake/FindLibrtmp.cmake b/CMake/FindLibrtmp.cmake index 50fc9692bd24..853ba63ad017 100644 --- a/CMake/FindLibrtmp.cmake +++ b/CMake/FindLibrtmp.cmake @@ -25,32 +25,29 @@ # # Input variables: # -# - `LIBRTMP_INCLUDE_DIR`: The librtmp include directory. -# - `LIBRTMP_LIBRARY`: Path to `librtmp` library. +# - `LIBRTMP_INCLUDE_DIR`: Absolute path to librtmp include directory. +# - `LIBRTMP_LIBRARY`: Absolute path to `librtmp` library. # -# Result variables: +# Defines: # -# - `LIBRTMP_FOUND`: System has librtmp. -# - `LIBRTMP_INCLUDE_DIRS`: The librtmp include directories. -# - `LIBRTMP_LIBRARIES`: The librtmp library names. -# - `LIBRTMP_LIBRARY_DIRS`: The librtmp library directories. -# - `LIBRTMP_PC_REQUIRES`: The librtmp pkg-config packages. -# - `LIBRTMP_CFLAGS`: Required compiler flags. -# - `LIBRTMP_VERSION`: Version of librtmp. +# - `LIBRTMP_FOUND`: System has librtmp. +# - `LIBRTMP_VERSION`: Version of librtmp. +# - `CURL::librtmp`: librtmp library target. -set(LIBRTMP_PC_REQUIRES "librtmp") +set(_librtmp_pc_requires "librtmp") if(CURL_USE_PKGCONFIG AND NOT DEFINED LIBRTMP_INCLUDE_DIR AND NOT DEFINED LIBRTMP_LIBRARY) find_package(PkgConfig QUIET) - pkg_check_modules(LIBRTMP ${LIBRTMP_PC_REQUIRES}) + pkg_check_modules(_librtmp ${_librtmp_pc_requires}) endif() -if(LIBRTMP_FOUND AND LIBRTMP_INCLUDE_DIRS) +if(_librtmp_FOUND AND _librtmp_INCLUDE_DIRS) set(Librtmp_FOUND TRUE) - string(REPLACE ";" " " LIBRTMP_CFLAGS "${LIBRTMP_CFLAGS}") - message(STATUS "Found Librtmp (via pkg-config): ${LIBRTMP_INCLUDE_DIRS} (found version \"${LIBRTMP_VERSION}\")") + set(LIBRTMP_FOUND TRUE) + set(LIBRTMP_VERSION ${_librtmp_VERSION}) + message(STATUS "Found Librtmp (via pkg-config): ${_librtmp_INCLUDE_DIRS} (found version \"${LIBRTMP_VERSION}\")") else() find_path(LIBRTMP_INCLUDE_DIR NAMES "librtmp/rtmp.h") find_library(LIBRTMP_LIBRARY NAMES "rtmp") @@ -85,19 +82,35 @@ else() ) if(LIBRTMP_FOUND) - set(LIBRTMP_INCLUDE_DIRS ${LIBRTMP_INCLUDE_DIR}) - set(LIBRTMP_LIBRARIES ${LIBRTMP_LIBRARY}) + set(_librtmp_INCLUDE_DIRS ${LIBRTMP_INCLUDE_DIR}) + set(_librtmp_LIBRARIES ${LIBRTMP_LIBRARY}) endif() mark_as_advanced(LIBRTMP_INCLUDE_DIR LIBRTMP_LIBRARY) # Necessary when linking a static librtmp find_package(OpenSSL) - if(OPENSSL_FOUND) - list(APPEND LIBRTMP_LIBRARIES OpenSSL::SSL OpenSSL::Crypto) + if(OpenSSL_FOUND) + list(APPEND _librtmp_LIBRARIES OpenSSL::SSL OpenSSL::Crypto) endif() endif() -if(LIBRTMP_FOUND AND WIN32) - list(APPEND LIBRTMP_LIBRARIES "winmm") +if(LIBRTMP_FOUND) + if(WIN32) + list(APPEND _librtmp_LIBRARIES "winmm") + endif() + + if(CMAKE_VERSION VERSION_LESS 3.13) + link_directories(${_librtmp_LIBRARY_DIRS}) + endif() + + if(NOT TARGET CURL::librtmp) + add_library(CURL::librtmp INTERFACE IMPORTED) + set_target_properties(CURL::librtmp PROPERTIES + INTERFACE_LIBCURL_PC_MODULES "${_librtmp_pc_requires}" + INTERFACE_COMPILE_OPTIONS "${_librtmp_CFLAGS}" + INTERFACE_INCLUDE_DIRECTORIES "${_librtmp_INCLUDE_DIRS}" + INTERFACE_LINK_DIRECTORIES "${_librtmp_LIBRARY_DIRS}" + INTERFACE_LINK_LIBRARIES "${_librtmp_LIBRARIES}") + endif() endif() diff --git a/CMake/FindLibssh.cmake b/CMake/FindLibssh.cmake index e2b27d975c3b..ad1248fe00af 100644 --- a/CMake/FindLibssh.cmake +++ b/CMake/FindLibssh.cmake @@ -25,32 +25,29 @@ # # Input variables: # -# - `LIBSSH_INCLUDE_DIR`: The libssh include directory. -# - `LIBSSH_LIBRARY`: Path to libssh library. +# - `LIBSSH_INCLUDE_DIR`: Absolute path to libssh include directory. +# - `LIBSSH_LIBRARY`: Absolute path to `libssh` library. # -# Result variables: +# Defines: # -# - `LIBSSH_FOUND`: System has libssh. -# - `LIBSSH_INCLUDE_DIRS`: The libssh include directories. -# - `LIBSSH_LIBRARIES`: The libssh library names. -# - `LIBSSH_LIBRARY_DIRS`: The libssh library directories. -# - `LIBSSH_PC_REQUIRES`: The libssh pkg-config packages. -# - `LIBSSH_CFLAGS`: Required compiler flags. -# - `LIBSSH_VERSION`: Version of libssh. +# - `LIBSSH_FOUND`: System has libssh. +# - `LIBSSH_VERSION`: Version of libssh. +# - `CURL::libssh`: libssh library target. -set(LIBSSH_PC_REQUIRES "libssh") +set(_libssh_pc_requires "libssh") if(CURL_USE_PKGCONFIG AND NOT DEFINED LIBSSH_INCLUDE_DIR AND NOT DEFINED LIBSSH_LIBRARY) find_package(PkgConfig QUIET) - pkg_check_modules(LIBSSH ${LIBSSH_PC_REQUIRES}) + pkg_check_modules(_libssh ${_libssh_pc_requires}) endif() -if(LIBSSH_FOUND) +if(_libssh_FOUND) set(Libssh_FOUND TRUE) - string(REPLACE ";" " " LIBSSH_CFLAGS "${LIBSSH_CFLAGS}") - message(STATUS "Found Libssh (via pkg-config): ${LIBSSH_INCLUDE_DIRS} (found version \"${LIBSSH_VERSION}\")") + set(LIBSSH_FOUND TRUE) + set(LIBSSH_VERSION ${_libssh_VERSION}) + message(STATUS "Found Libssh (via pkg-config): ${_libssh_INCLUDE_DIRS} (found version \"${LIBSSH_VERSION}\")") else() find_path(LIBSSH_INCLUDE_DIR NAMES "libssh/libssh.h") find_library(LIBSSH_LIBRARY NAMES "ssh" "libssh") @@ -85,13 +82,29 @@ else() ) if(LIBSSH_FOUND) - set(LIBSSH_INCLUDE_DIRS ${LIBSSH_INCLUDE_DIR}) - set(LIBSSH_LIBRARIES ${LIBSSH_LIBRARY}) + set(_libssh_INCLUDE_DIRS ${LIBSSH_INCLUDE_DIR}) + set(_libssh_LIBRARIES ${LIBSSH_LIBRARY}) endif() mark_as_advanced(LIBSSH_INCLUDE_DIR LIBSSH_LIBRARY) endif() -if(LIBSSH_FOUND AND WIN32) - list(APPEND LIBSSH_LIBRARIES "iphlpapi") # for if_nametoindex +if(LIBSSH_FOUND) + if(WIN32) + list(APPEND _libssh_LIBRARIES "iphlpapi") # for if_nametoindex + endif() + + if(CMAKE_VERSION VERSION_LESS 3.13) + link_directories(${_libssh_LIBRARY_DIRS}) + endif() + + if(NOT TARGET CURL::libssh) + add_library(CURL::libssh INTERFACE IMPORTED) + set_target_properties(CURL::libssh PROPERTIES + INTERFACE_LIBCURL_PC_MODULES "${_libssh_pc_requires}" + INTERFACE_COMPILE_OPTIONS "${_libssh_CFLAGS}" + INTERFACE_INCLUDE_DIRECTORIES "${_libssh_INCLUDE_DIRS}" + INTERFACE_LINK_DIRECTORIES "${_libssh_LIBRARY_DIRS}" + INTERFACE_LINK_LIBRARIES "${_libssh_LIBRARIES}") + endif() endif() diff --git a/CMake/FindLibssh2.cmake b/CMake/FindLibssh2.cmake index 0b81ecb3cfcb..330611bfe55c 100644 --- a/CMake/FindLibssh2.cmake +++ b/CMake/FindLibssh2.cmake @@ -25,32 +25,29 @@ # # Input variables: # -# - `LIBSSH2_INCLUDE_DIR`: The libssh2 include directory. -# - `LIBSSH2_LIBRARY`: Path to `libssh2` library. +# - `LIBSSH2_INCLUDE_DIR`: Absolute path to libssh2 include directory. +# - `LIBSSH2_LIBRARY`: Absolute path to `libssh2` library. # -# Result variables: +# Defines: # -# - `LIBSSH2_FOUND`: System has libssh2. -# - `LIBSSH2_INCLUDE_DIRS`: The libssh2 include directories. -# - `LIBSSH2_LIBRARIES`: The libssh2 library names. -# - `LIBSSH2_LIBRARY_DIRS`: The libssh2 library directories. -# - `LIBSSH2_PC_REQUIRES`: The libssh2 pkg-config packages. -# - `LIBSSH2_CFLAGS`: Required compiler flags. -# - `LIBSSH2_VERSION`: Version of libssh2. +# - `LIBSSH2_FOUND`: System has libssh2. +# - `LIBSSH2_VERSION`: Version of libssh2. +# - `CURL::libssh2`: libssh2 library target. -set(LIBSSH2_PC_REQUIRES "libssh2") +set(_libssh2_pc_requires "libssh2") if(CURL_USE_PKGCONFIG AND NOT DEFINED LIBSSH2_INCLUDE_DIR AND NOT DEFINED LIBSSH2_LIBRARY) find_package(PkgConfig QUIET) - pkg_check_modules(LIBSSH2 ${LIBSSH2_PC_REQUIRES}) + pkg_check_modules(_libssh2 ${_libssh2_pc_requires}) endif() -if(LIBSSH2_FOUND AND LIBSSH2_INCLUDE_DIRS) +if(_libssh2_FOUND AND _libssh2_INCLUDE_DIRS) set(Libssh2_FOUND TRUE) - string(REPLACE ";" " " LIBSSH2_CFLAGS "${LIBSSH2_CFLAGS}") - message(STATUS "Found Libssh2 (via pkg-config): ${LIBSSH2_INCLUDE_DIRS} (found version \"${LIBSSH2_VERSION}\")") + set(LIBSSH2_FOUND TRUE) + set(LIBSSH2_VERSION ${_libssh2_VERSION}) + message(STATUS "Found Libssh2 (via pkg-config): ${_libssh2_INCLUDE_DIRS} (found version \"${LIBSSH2_VERSION}\")") else() find_path(LIBSSH2_INCLUDE_DIR NAMES "libssh2.h") find_library(LIBSSH2_LIBRARY NAMES "ssh2" "libssh2") @@ -75,9 +72,25 @@ else() ) if(LIBSSH2_FOUND) - set(LIBSSH2_INCLUDE_DIRS ${LIBSSH2_INCLUDE_DIR}) - set(LIBSSH2_LIBRARIES ${LIBSSH2_LIBRARY}) + set(_libssh2_INCLUDE_DIRS ${LIBSSH2_INCLUDE_DIR}) + set(_libssh2_LIBRARIES ${LIBSSH2_LIBRARY}) endif() mark_as_advanced(LIBSSH2_INCLUDE_DIR LIBSSH2_LIBRARY) endif() + +if(LIBSSH2_FOUND) + if(CMAKE_VERSION VERSION_LESS 3.13) + link_directories(${_libssh2_LIBRARY_DIRS}) + endif() + + if(NOT TARGET CURL::libssh2) + add_library(CURL::libssh2 INTERFACE IMPORTED) + set_target_properties(CURL::libssh2 PROPERTIES + INTERFACE_LIBCURL_PC_MODULES "${_libssh2_pc_requires}" + INTERFACE_COMPILE_OPTIONS "${_libssh2_CFLAGS}" + INTERFACE_INCLUDE_DIRECTORIES "${_libssh2_INCLUDE_DIRS}" + INTERFACE_LINK_DIRECTORIES "${_libssh2_LIBRARY_DIRS}" + INTERFACE_LINK_LIBRARIES "${_libssh2_LIBRARIES}") + endif() +endif() diff --git a/CMake/FindLibuv.cmake b/CMake/FindLibuv.cmake index b16b3554f651..f9d614bc067c 100644 --- a/CMake/FindLibuv.cmake +++ b/CMake/FindLibuv.cmake @@ -25,32 +25,29 @@ # # Input variables: # -# - `LIBUV_INCLUDE_DIR`: The libuv include directory. -# - `LIBUV_LIBRARY`: Path to `libuv` library. +# - `LIBUV_INCLUDE_DIR`: Absolute path to libuv include directory. +# - `LIBUV_LIBRARY`: Absolute path to `libuv` library. # -# Result variables: +# Defines: # -# - `LIBUV_FOUND`: System has libuv. -# - `LIBUV_INCLUDE_DIRS`: The libuv include directories. -# - `LIBUV_LIBRARIES`: The libuv library names. -# - `LIBUV_LIBRARY_DIRS`: The libuv library directories. -# - `LIBUV_PC_REQUIRES`: The libuv pkg-config packages. -# - `LIBUV_CFLAGS`: Required compiler flags. -# - `LIBUV_VERSION`: Version of libuv. +# - `LIBUV_FOUND`: System has libuv. +# - `LIBUV_VERSION`: Version of libuv. +# - `CURL::libuv`: libuv library target. -set(LIBUV_PC_REQUIRES "libuv") +set(_libuv_pc_requires "libuv") if(CURL_USE_PKGCONFIG AND NOT DEFINED LIBUV_INCLUDE_DIR AND NOT DEFINED LIBUV_LIBRARY) find_package(PkgConfig QUIET) - pkg_check_modules(LIBUV ${LIBUV_PC_REQUIRES}) + pkg_check_modules(_libuv ${_libuv_pc_requires}) endif() -if(LIBUV_FOUND) +if(_libuv_FOUND) set(Libuv_FOUND TRUE) - string(REPLACE ";" " " LIBUV_CFLAGS "${LIBUV_CFLAGS}") - message(STATUS "Found Libuv (via pkg-config): ${LIBUV_INCLUDE_DIRS} (found version \"${LIBUV_VERSION}\")") + set(LIBUV_FOUND TRUE) + set(LIBUV_VERSION ${_libuv_VERSION}) + message(STATUS "Found Libuv (via pkg-config): ${_libuv_INCLUDE_DIRS} (found version \"${LIBUV_VERSION}\")") else() find_path(LIBUV_INCLUDE_DIR NAMES "uv.h") find_library(LIBUV_LIBRARY NAMES "uv" "libuv") @@ -85,9 +82,25 @@ else() ) if(LIBUV_FOUND) - set(LIBUV_INCLUDE_DIRS ${LIBUV_INCLUDE_DIR}) - set(LIBUV_LIBRARIES ${LIBUV_LIBRARY}) + set(_libuv_INCLUDE_DIRS ${LIBUV_INCLUDE_DIR}) + set(_libuv_LIBRARIES ${LIBUV_LIBRARY}) endif() mark_as_advanced(LIBUV_INCLUDE_DIR LIBUV_LIBRARY) endif() + +if(LIBUV_FOUND) + if(CMAKE_VERSION VERSION_LESS 3.13) + link_directories(${_libuv_LIBRARY_DIRS}) + endif() + + if(NOT TARGET CURL::libuv) + add_library(CURL::libuv INTERFACE IMPORTED) + set_target_properties(CURL::libuv PROPERTIES + INTERFACE_LIBCURL_PC_MODULES "${_libuv_pc_requires}" + INTERFACE_COMPILE_OPTIONS "${_libuv_CFLAGS}" + INTERFACE_INCLUDE_DIRECTORIES "${_libuv_INCLUDE_DIRS}" + INTERFACE_LINK_DIRECTORIES "${_libuv_LIBRARY_DIRS}" + INTERFACE_LINK_LIBRARIES "${_libuv_LIBRARIES}") + endif() +endif() diff --git a/CMake/FindMbedTLS.cmake b/CMake/FindMbedTLS.cmake index 4b5a6121f193..97201ab2b343 100644 --- a/CMake/FindMbedTLS.cmake +++ b/CMake/FindMbedTLS.cmake @@ -25,20 +25,16 @@ # # Input variables: # -# - `MBEDTLS_INCLUDE_DIR`: The mbedTLS include directory. -# - `MBEDTLS_LIBRARY`: Path to `mbedtls` library. -# - `MBEDX509_LIBRARY`: Path to `mbedx509` library. -# - `MBEDCRYPTO_LIBRARY`: Path to `mbedcrypto` library. +# - `MBEDTLS_INCLUDE_DIR`: Absolute path to mbedTLS include directory. +# - `MBEDTLS_LIBRARY`: Absolute path to `mbedtls` library. +# - `MBEDX509_LIBRARY`: Absolute path to `mbedx509` library. +# - `MBEDCRYPTO_LIBRARY`: Absolute path to `mbedcrypto` library. # -# Result variables: +# Defines: # -# - `MBEDTLS_FOUND`: System has mbedTLS. -# - `MBEDTLS_INCLUDE_DIRS`: The mbedTLS include directories. -# - `MBEDTLS_LIBRARIES`: The mbedTLS library names. -# - `MBEDTLS_LIBRARY_DIRS`: The mbedTLS library directories. -# - `MBEDTLS_PC_REQUIRES`: The mbedTLS pkg-config packages. -# - `MBEDTLS_CFLAGS`: Required compiler flags. -# - `MBEDTLS_VERSION`: Version of mbedTLS. +# - `MBEDTLS_FOUND`: System has mbedTLS. +# - `MBEDTLS_VERSION`: Version of mbedTLS. +# - `CURL::mbedtls`: mbedTLS library target. if(DEFINED MBEDTLS_INCLUDE_DIRS AND NOT DEFINED MBEDTLS_INCLUDE_DIR) message(WARNING "MBEDTLS_INCLUDE_DIRS is deprecated, use MBEDTLS_INCLUDE_DIR instead.") @@ -46,7 +42,7 @@ if(DEFINED MBEDTLS_INCLUDE_DIRS AND NOT DEFINED MBEDTLS_INCLUDE_DIR) unset(MBEDTLS_INCLUDE_DIRS) endif() -set(MBEDTLS_PC_REQUIRES "mbedtls" "mbedx509" "mbedcrypto") +set(_mbedtls_pc_requires "mbedtls" "mbedx509" "mbedcrypto") if(CURL_USE_PKGCONFIG AND NOT DEFINED MBEDTLS_INCLUDE_DIR AND @@ -54,16 +50,16 @@ if(CURL_USE_PKGCONFIG AND NOT DEFINED MBEDX509_LIBRARY AND NOT DEFINED MBEDCRYPTO_LIBRARY) find_package(PkgConfig QUIET) - pkg_check_modules(MBEDTLS ${MBEDTLS_PC_REQUIRES}) + pkg_check_modules(_mbedtls ${_mbedtls_pc_requires}) endif() -if(MBEDTLS_FOUND) +if(_mbedtls_FOUND) set(MbedTLS_FOUND TRUE) - set(MBEDTLS_VERSION "${MBEDTLS_mbedtls_VERSION}") - string(REPLACE ";" " " MBEDTLS_CFLAGS "${MBEDTLS_CFLAGS}") - message(STATUS "Found MbedTLS (via pkg-config): ${MBEDTLS_INCLUDE_DIRS} (found version \"${MBEDTLS_VERSION}\")") + set(MBEDTLS_FOUND TRUE) + set(MBEDTLS_VERSION ${_mbedtls_mbedtls_VERSION}) + message(STATUS "Found MbedTLS (via pkg-config): ${_mbedtls_INCLUDE_DIRS} (found version \"${MBEDTLS_VERSION}\")") else() - set(MBEDTLS_PC_REQUIRES "") # Depend on pkg-config only when found via pkg-config + set(_mbedtls_pc_requires "") # Depend on pkg-config only when found via pkg-config find_path(MBEDTLS_INCLUDE_DIR NAMES "mbedtls/ssl.h") find_library(MBEDTLS_LIBRARY NAMES "mbedtls" "libmbedtls") @@ -92,9 +88,25 @@ else() ) if(MBEDTLS_FOUND) - set(MBEDTLS_INCLUDE_DIRS ${MBEDTLS_INCLUDE_DIR}) - set(MBEDTLS_LIBRARIES ${MBEDTLS_LIBRARY} ${MBEDX509_LIBRARY} ${MBEDCRYPTO_LIBRARY}) + set(_mbedtls_INCLUDE_DIRS ${MBEDTLS_INCLUDE_DIR}) + set(_mbedtls_LIBRARIES ${MBEDTLS_LIBRARY} ${MBEDX509_LIBRARY} ${MBEDCRYPTO_LIBRARY}) endif() mark_as_advanced(MBEDTLS_INCLUDE_DIR MBEDTLS_LIBRARY MBEDX509_LIBRARY MBEDCRYPTO_LIBRARY) endif() + +if(MBEDTLS_FOUND) + if(CMAKE_VERSION VERSION_LESS 3.13) + link_directories(${_mbedtls_LIBRARY_DIRS}) + endif() + + if(NOT TARGET CURL::mbedtls) + add_library(CURL::mbedtls INTERFACE IMPORTED) + set_target_properties(CURL::mbedtls PROPERTIES + INTERFACE_LIBCURL_PC_MODULES "${_mbedtls_pc_requires}" + INTERFACE_COMPILE_OPTIONS "${_mbedtls_CFLAGS}" + INTERFACE_INCLUDE_DIRECTORIES "${_mbedtls_INCLUDE_DIRS}" + INTERFACE_LINK_DIRECTORIES "${_mbedtls_LIBRARY_DIRS}" + INTERFACE_LINK_LIBRARIES "${_mbedtls_LIBRARIES}") + endif() +endif() diff --git a/CMake/FindNGHTTP2.cmake b/CMake/FindNGHTTP2.cmake index b8f37fdaebf1..8304345a384b 100644 --- a/CMake/FindNGHTTP2.cmake +++ b/CMake/FindNGHTTP2.cmake @@ -25,31 +25,28 @@ # # Input variables: # -# - `NGHTTP2_INCLUDE_DIR`: The nghttp2 include directory. -# - `NGHTTP2_LIBRARY`: Path to `nghttp2` library. +# - `NGHTTP2_INCLUDE_DIR`: Absolute path to nghttp2 include directory. +# - `NGHTTP2_LIBRARY`: Absolute path to `nghttp2` library. # -# Result variables: +# Defines: # -# - `NGHTTP2_FOUND`: System has nghttp2. -# - `NGHTTP2_INCLUDE_DIRS`: The nghttp2 include directories. -# - `NGHTTP2_LIBRARIES`: The nghttp2 library names. -# - `NGHTTP2_LIBRARY_DIRS`: The nghttp2 library directories. -# - `NGHTTP2_PC_REQUIRES`: The nghttp2 pkg-config packages. -# - `NGHTTP2_CFLAGS`: Required compiler flags. -# - `NGHTTP2_VERSION`: Version of nghttp2. +# - `NGHTTP2_FOUND`: System has nghttp2. +# - `NGHTTP2_VERSION`: Version of nghttp2. +# - `CURL::nghttp2`: nghttp2 library target. -set(NGHTTP2_PC_REQUIRES "libnghttp2") +set(_nghttp2_pc_requires "libnghttp2") if(CURL_USE_PKGCONFIG AND NOT DEFINED NGHTTP2_INCLUDE_DIR AND NOT DEFINED NGHTTP2_LIBRARY) find_package(PkgConfig QUIET) - pkg_check_modules(NGHTTP2 ${NGHTTP2_PC_REQUIRES}) + pkg_check_modules(_nghttp2 ${_nghttp2_pc_requires}) endif() -if(NGHTTP2_FOUND) - string(REPLACE ";" " " NGHTTP2_CFLAGS "${NGHTTP2_CFLAGS}") - message(STATUS "Found NGHTTP2 (via pkg-config): ${NGHTTP2_INCLUDE_DIRS} (found version \"${NGHTTP2_VERSION}\")") +if(_nghttp2_FOUND) + set(NGHTTP2_FOUND TRUE) + set(NGHTTP2_VERSION ${_nghttp2_VERSION}) + message(STATUS "Found NGHTTP2 (via pkg-config): ${_nghttp2_INCLUDE_DIRS} (found version \"${NGHTTP2_VERSION}\")") else() find_path(NGHTTP2_INCLUDE_DIR NAMES "nghttp2/nghttp2.h") find_library(NGHTTP2_LIBRARY NAMES "nghttp2" "nghttp2_static") @@ -74,9 +71,25 @@ else() ) if(NGHTTP2_FOUND) - set(NGHTTP2_INCLUDE_DIRS ${NGHTTP2_INCLUDE_DIR}) - set(NGHTTP2_LIBRARIES ${NGHTTP2_LIBRARY}) + set(_nghttp2_INCLUDE_DIRS ${NGHTTP2_INCLUDE_DIR}) + set(_nghttp2_LIBRARIES ${NGHTTP2_LIBRARY}) endif() mark_as_advanced(NGHTTP2_INCLUDE_DIR NGHTTP2_LIBRARY) endif() + +if(NGHTTP2_FOUND) + if(CMAKE_VERSION VERSION_LESS 3.13) + link_directories(${_nghttp2_LIBRARY_DIRS}) + endif() + + if(NOT TARGET CURL::nghttp2) + add_library(CURL::nghttp2 INTERFACE IMPORTED) + set_target_properties(CURL::nghttp2 PROPERTIES + INTERFACE_LIBCURL_PC_MODULES "${_nghttp2_pc_requires}" + INTERFACE_COMPILE_OPTIONS "${_nghttp2_CFLAGS}" + INTERFACE_INCLUDE_DIRECTORIES "${_nghttp2_INCLUDE_DIRS}" + INTERFACE_LINK_DIRECTORIES "${_nghttp2_LIBRARY_DIRS}" + INTERFACE_LINK_LIBRARIES "${_nghttp2_LIBRARIES}") + endif() +endif() diff --git a/CMake/FindNGHTTP3.cmake b/CMake/FindNGHTTP3.cmake index 99edd19955ed..37ebfe1114fa 100644 --- a/CMake/FindNGHTTP3.cmake +++ b/CMake/FindNGHTTP3.cmake @@ -25,31 +25,28 @@ # # Input variables: # -# - `NGHTTP3_INCLUDE_DIR`: The nghttp3 include directory. -# - `NGHTTP3_LIBRARY`: Path to `nghttp3` library. +# - `NGHTTP3_INCLUDE_DIR`: Absolute path to nghttp3 include directory. +# - `NGHTTP3_LIBRARY`: Absolute path to `nghttp3` library. # -# Result variables: +# Defines: # -# - `NGHTTP3_FOUND`: System has nghttp3. -# - `NGHTTP3_INCLUDE_DIRS`: The nghttp3 include directories. -# - `NGHTTP3_LIBRARIES`: The nghttp3 library names. -# - `NGHTTP3_LIBRARY_DIRS`: The nghttp3 library directories. -# - `NGHTTP3_PC_REQUIRES`: The nghttp3 pkg-config packages. -# - `NGHTTP3_CFLAGS`: Required compiler flags. -# - `NGHTTP3_VERSION`: Version of nghttp3. +# - `NGHTTP3_FOUND`: System has nghttp3. +# - `NGHTTP3_VERSION`: Version of nghttp3. +# - `CURL::nghttp3`: nghttp3 library target. -set(NGHTTP3_PC_REQUIRES "libnghttp3") +set(_nghttp3_pc_requires "libnghttp3") if(CURL_USE_PKGCONFIG AND NOT DEFINED NGHTTP3_INCLUDE_DIR AND NOT DEFINED NGHTTP3_LIBRARY) find_package(PkgConfig QUIET) - pkg_check_modules(NGHTTP3 ${NGHTTP3_PC_REQUIRES}) + pkg_check_modules(_nghttp3 ${_nghttp3_pc_requires}) endif() -if(NGHTTP3_FOUND) - string(REPLACE ";" " " NGHTTP3_CFLAGS "${NGHTTP3_CFLAGS}") - message(STATUS "Found NGHTTP3 (via pkg-config): ${NGHTTP3_INCLUDE_DIRS} (found version \"${NGHTTP3_VERSION}\")") +if(_nghttp3_FOUND) + set(NGHTTP3_FOUND TRUE) + set(NGHTTP3_VERSION ${_nghttp3_VERSION}) + message(STATUS "Found NGHTTP3 (via pkg-config): ${_nghttp3_INCLUDE_DIRS} (found version \"${NGHTTP3_VERSION}\")") else() find_path(NGHTTP3_INCLUDE_DIR NAMES "nghttp3/nghttp3.h") find_library(NGHTTP3_LIBRARY NAMES "nghttp3") @@ -74,9 +71,25 @@ else() ) if(NGHTTP3_FOUND) - set(NGHTTP3_INCLUDE_DIRS ${NGHTTP3_INCLUDE_DIR}) - set(NGHTTP3_LIBRARIES ${NGHTTP3_LIBRARY}) + set(_nghttp3_INCLUDE_DIRS ${NGHTTP3_INCLUDE_DIR}) + set(_nghttp3_LIBRARIES ${NGHTTP3_LIBRARY}) endif() mark_as_advanced(NGHTTP3_INCLUDE_DIR NGHTTP3_LIBRARY) endif() + +if(NGHTTP3_FOUND) + if(CMAKE_VERSION VERSION_LESS 3.13) + link_directories(${_nghttp3_LIBRARY_DIRS}) + endif() + + if(NOT TARGET CURL::nghttp3) + add_library(CURL::nghttp3 INTERFACE IMPORTED) + set_target_properties(CURL::nghttp3 PROPERTIES + INTERFACE_LIBCURL_PC_MODULES "${_nghttp3_pc_requires}" + INTERFACE_COMPILE_OPTIONS "${_nghttp3_CFLAGS}" + INTERFACE_INCLUDE_DIRECTORIES "${_nghttp3_INCLUDE_DIRS}" + INTERFACE_LINK_DIRECTORIES "${_nghttp3_LIBRARY_DIRS}" + INTERFACE_LINK_LIBRARIES "${_nghttp3_LIBRARIES}") + endif() +endif() diff --git a/CMake/FindNGTCP2.cmake b/CMake/FindNGTCP2.cmake index eb4358ef00a7..416ea459f6b1 100644 --- a/CMake/FindNGTCP2.cmake +++ b/CMake/FindNGTCP2.cmake @@ -35,24 +35,20 @@ # # Input variables: # -# - `NGTCP2_INCLUDE_DIR`: The ngtcp2 include directory. -# - `NGTCP2_LIBRARY`: Path to `ngtcp2` library. -# - `NGTCP2_CRYPTO_BORINGSSL_LIBRARY`: Path to `ngtcp2_crypto_boringssl` library. -# - `NGTCP2_CRYPTO_GNUTLS_LIBRARY`: Path to `ngtcp2_crypto_gnutls` library. -# - `NGTCP2_CRYPTO_LIBRESSL_LIBRARY`: Path to `ngtcp2_crypto_libressl` library. -# - `NGTCP2_CRYPTO_OSSL_LIBRARY`: Path to `ngtcp2_crypto_ossl` library. -# - `NGTCP2_CRYPTO_QUICTLS_LIBRARY`: Path to `ngtcp2_crypto_quictls` library. -# - `NGTCP2_CRYPTO_WOLFSSL_LIBRARY`: Path to `ngtcp2_crypto_wolfssl` library. +# - `NGTCP2_INCLUDE_DIR`: Absolute path to ngtcp2 include directory. +# - `NGTCP2_LIBRARY`: Absolute path to `ngtcp2` library. +# - `NGTCP2_CRYPTO_BORINGSSL_LIBRARY`: Absolute path to `ngtcp2_crypto_boringssl` library. +# - `NGTCP2_CRYPTO_GNUTLS_LIBRARY`: Absolute path to `ngtcp2_crypto_gnutls` library. +# - `NGTCP2_CRYPTO_LIBRESSL_LIBRARY`: Absolute path to `ngtcp2_crypto_libressl` library. +# - `NGTCP2_CRYPTO_OSSL_LIBRARY`: Absolute path to `ngtcp2_crypto_ossl` library. +# - `NGTCP2_CRYPTO_QUICTLS_LIBRARY`: Absolute path to `ngtcp2_crypto_quictls` library. +# - `NGTCP2_CRYPTO_WOLFSSL_LIBRARY`: Absolute path to `ngtcp2_crypto_wolfssl` library. # -# Result variables: +# Defines: # # - `NGTCP2_FOUND`: System has ngtcp2. -# - `NGTCP2_INCLUDE_DIRS`: The ngtcp2 include directories. -# - `NGTCP2_LIBRARIES`: The ngtcp2 library names. -# - `NGTCP2_LIBRARY_DIRS`: The ngtcp2 library directories. -# - `NGTCP2_PC_REQUIRES`: The ngtcp2 pkg-config packages. -# - `NGTCP2_CFLAGS`: Required compiler flags. # - `NGTCP2_VERSION`: Version of ngtcp2. +# - `CURL::ngtcp2`: ngtcp2 library target. if(NGTCP2_FIND_COMPONENTS) set(_ngtcp2_crypto_backend "") @@ -71,9 +67,9 @@ if(NGTCP2_FIND_COMPONENTS) endif() endif() -set(NGTCP2_PC_REQUIRES "libngtcp2") +set(_ngtcp2_pc_requires "libngtcp2") if(_ngtcp2_crypto_backend) - list(APPEND NGTCP2_PC_REQUIRES "lib${_crypto_library_lower}") + list(APPEND _ngtcp2_pc_requires "lib${_crypto_library_lower}") endif() set(_tried_pkgconfig FALSE) @@ -81,14 +77,14 @@ if(CURL_USE_PKGCONFIG AND NOT DEFINED NGTCP2_INCLUDE_DIR AND NOT DEFINED NGTCP2_LIBRARY) find_package(PkgConfig QUIET) - pkg_check_modules(NGTCP2 ${NGTCP2_PC_REQUIRES}) + pkg_check_modules(_ngtcp2 ${_ngtcp2_pc_requires}) set(_tried_pkgconfig TRUE) endif() -if(NGTCP2_FOUND) - set(NGTCP2_VERSION "${NGTCP2_libngtcp2_VERSION}") - string(REPLACE ";" " " NGTCP2_CFLAGS "${NGTCP2_CFLAGS}") - message(STATUS "Found NGTCP2 (via pkg-config): ${NGTCP2_INCLUDE_DIRS} (found version \"${NGTCP2_VERSION}\")") +if(_ngtcp2_FOUND) + set(NGTCP2_FOUND TRUE) + set(NGTCP2_VERSION ${_ngtcp2_libngtcp2_VERSION}) + message(STATUS "Found NGTCP2 (via pkg-config): ${_ngtcp2_INCLUDE_DIRS} (found version \"${NGTCP2_VERSION}\")") else() find_path(NGTCP2_INCLUDE_DIR NAMES "ngtcp2/ngtcp2.h") find_library(NGTCP2_LIBRARY NAMES "ngtcp2") @@ -128,8 +124,8 @@ else() ) if(NGTCP2_FOUND) - set(NGTCP2_INCLUDE_DIRS ${NGTCP2_INCLUDE_DIR}) - set(NGTCP2_LIBRARIES ${NGTCP2_LIBRARY} ${NGTCP2_CRYPTO_LIBRARY}) + set(_ngtcp2_INCLUDE_DIRS ${NGTCP2_INCLUDE_DIR}) + set(_ngtcp2_LIBRARIES ${NGTCP2_LIBRARY} ${NGTCP2_CRYPTO_LIBRARY}) endif() mark_as_advanced(NGTCP2_INCLUDE_DIR NGTCP2_LIBRARY NGTCP2_CRYPTO_LIBRARY) @@ -139,3 +135,19 @@ else() unset(NGTCP2_LIBRARY CACHE) endif() endif() + +if(NGTCP2_FOUND) + if(CMAKE_VERSION VERSION_LESS 3.13) + link_directories(${_ngtcp2_LIBRARY_DIRS}) + endif() + + if(NOT TARGET CURL::ngtcp2) + add_library(CURL::ngtcp2 INTERFACE IMPORTED) + set_target_properties(CURL::ngtcp2 PROPERTIES + INTERFACE_LIBCURL_PC_MODULES "${_ngtcp2_pc_requires}" + INTERFACE_COMPILE_OPTIONS "${_ngtcp2_CFLAGS}" + INTERFACE_INCLUDE_DIRECTORIES "${_ngtcp2_INCLUDE_DIRS}" + INTERFACE_LINK_DIRECTORIES "${_ngtcp2_LIBRARY_DIRS}" + INTERFACE_LINK_LIBRARIES "${_ngtcp2_LIBRARIES}") + endif() +endif() diff --git a/CMake/FindNettle.cmake b/CMake/FindNettle.cmake index c2decf6e7b08..d22865ffad69 100644 --- a/CMake/FindNettle.cmake +++ b/CMake/FindNettle.cmake @@ -25,32 +25,29 @@ # # Input variables: # -# - `NETTLE_INCLUDE_DIR`: The nettle include directory. -# - `NETTLE_LIBRARY`: Path to `nettle` library. +# - `NETTLE_INCLUDE_DIR`: Absolute path to nettle include directory. +# - `NETTLE_LIBRARY`: Absolute path to `nettle` library. # -# Result variables: +# Defines: # -# - `NETTLE_FOUND`: System has nettle. -# - `NETTLE_INCLUDE_DIRS`: The nettle include directories. -# - `NETTLE_LIBRARIES`: The nettle library names. -# - `NETTLE_LIBRARY_DIRS`: The nettle library directories. -# - `NETTLE_PC_REQUIRES`: The nettle pkg-config packages. -# - `NETTLE_CFLAGS`: Required compiler flags. -# - `NETTLE_VERSION`: Version of nettle. +# - `NETTLE_FOUND`: System has nettle. +# - `NETTLE_VERSION`: Version of nettle. +# - `CURL::nettle`: nettle library target. -set(NETTLE_PC_REQUIRES "nettle") +set(_nettle_pc_requires "nettle") if(CURL_USE_PKGCONFIG AND NOT DEFINED NETTLE_INCLUDE_DIR AND NOT DEFINED NETTLE_LIBRARY) find_package(PkgConfig QUIET) - pkg_check_modules(NETTLE ${NETTLE_PC_REQUIRES}) + pkg_check_modules(_nettle ${_nettle_pc_requires}) endif() -if(NETTLE_FOUND) +if(_nettle_FOUND) set(Nettle_FOUND TRUE) - string(REPLACE ";" " " NETTLE_CFLAGS "${NETTLE_CFLAGS}") - message(STATUS "Found Nettle (via pkg-config): ${NETTLE_INCLUDE_DIRS} (found version \"${NETTLE_VERSION}\")") + set(NETTLE_FOUND TRUE) + set(NETTLE_VERSION ${_nettle_VERSION}) + message(STATUS "Found Nettle (via pkg-config): ${_nettle_INCLUDE_DIRS} (found version \"${NETTLE_VERSION}\")") else() find_path(NETTLE_INCLUDE_DIR NAMES "nettle/sha2.h") find_library(NETTLE_LIBRARY NAMES "nettle") @@ -80,9 +77,25 @@ else() ) if(NETTLE_FOUND) - set(NETTLE_INCLUDE_DIRS ${NETTLE_INCLUDE_DIR}) - set(NETTLE_LIBRARIES ${NETTLE_LIBRARY}) + set(_nettle_INCLUDE_DIRS ${NETTLE_INCLUDE_DIR}) + set(_nettle_LIBRARIES ${NETTLE_LIBRARY}) endif() mark_as_advanced(NETTLE_INCLUDE_DIR NETTLE_LIBRARY) endif() + +if(NETTLE_FOUND) + if(CMAKE_VERSION VERSION_LESS 3.13) + link_directories(${_nettle_LIBRARY_DIRS}) + endif() + + if(NOT TARGET CURL::nettle) + add_library(CURL::nettle INTERFACE IMPORTED) + set_target_properties(CURL::nettle PROPERTIES + INTERFACE_LIBCURL_PC_MODULES "${_nettle_pc_requires}" + INTERFACE_COMPILE_OPTIONS "${_nettle_CFLAGS}" + INTERFACE_INCLUDE_DIRECTORIES "${_nettle_INCLUDE_DIRS}" + INTERFACE_LINK_DIRECTORIES "${_nettle_LIBRARY_DIRS}" + INTERFACE_LINK_LIBRARIES "${_nettle_LIBRARIES}") + endif() +endif() diff --git a/CMake/FindQuiche.cmake b/CMake/FindQuiche.cmake index 6939c64e0ff9..22482d79fb4f 100644 --- a/CMake/FindQuiche.cmake +++ b/CMake/FindQuiche.cmake @@ -25,32 +25,29 @@ # # Input variables: # -# - `QUICHE_INCLUDE_DIR`: The quiche include directory. -# - `QUICHE_LIBRARY`: Path to `quiche` library. +# - `QUICHE_INCLUDE_DIR`: Absolute path to quiche include directory. +# - `QUICHE_LIBRARY`: Absolute path to `quiche` library. # -# Result variables: +# Defines: # -# - `QUICHE_FOUND`: System has quiche. -# - `QUICHE_INCLUDE_DIRS`: The quiche include directories. -# - `QUICHE_LIBRARIES`: The quiche library names. -# - `QUICHE_LIBRARY_DIRS`: The quiche library directories. -# - `QUICHE_PC_REQUIRES`: The quiche pkg-config packages. -# - `QUICHE_CFLAGS`: Required compiler flags. -# - `QUICHE_VERSION`: Version of quiche. +# - `QUICHE_FOUND`: System has quiche. +# - `QUICHE_VERSION`: Version of quiche. +# - `CURL::quiche`: quiche library target. -set(QUICHE_PC_REQUIRES "quiche") +set(_quiche_pc_requires "quiche") if(CURL_USE_PKGCONFIG AND NOT DEFINED QUICHE_INCLUDE_DIR AND NOT DEFINED QUICHE_LIBRARY) find_package(PkgConfig QUIET) - pkg_check_modules(QUICHE ${QUICHE_PC_REQUIRES}) + pkg_check_modules(_quiche ${_quiche_pc_requires}) endif() -if(QUICHE_FOUND) +if(_quiche_FOUND) set(Quiche_FOUND TRUE) - string(REPLACE ";" " " QUICHE_CFLAGS "${QUICHE_CFLAGS}") - message(STATUS "Found Quiche (via pkg-config): ${QUICHE_INCLUDE_DIRS} (found version \"${QUICHE_VERSION}\")") + set(QUICHE_FOUND TRUE) + set(QUICHE_VERSION ${_quiche_VERSION}) + message(STATUS "Found Quiche (via pkg-config): ${_quiche_INCLUDE_DIRS} (found version \"${QUICHE_VERSION}\")") else() find_path(QUICHE_INCLUDE_DIR NAMES "quiche.h") find_library(QUICHE_LIBRARY NAMES "quiche") @@ -63,9 +60,25 @@ else() ) if(QUICHE_FOUND) - set(QUICHE_INCLUDE_DIRS ${QUICHE_INCLUDE_DIR}) - set(QUICHE_LIBRARIES ${QUICHE_LIBRARY}) + set(_quiche_INCLUDE_DIRS ${QUICHE_INCLUDE_DIR}) + set(_quiche_LIBRARIES ${QUICHE_LIBRARY}) endif() mark_as_advanced(QUICHE_INCLUDE_DIR QUICHE_LIBRARY) endif() + +if(QUICHE_FOUND) + if(CMAKE_VERSION VERSION_LESS 3.13) + link_directories(${_quiche_LIBRARY_DIRS}) + endif() + + if(NOT TARGET CURL::quiche) + add_library(CURL::quiche INTERFACE IMPORTED) + set_target_properties(CURL::quiche PROPERTIES + INTERFACE_LIBCURL_PC_MODULES "${_quiche_pc_requires}" + INTERFACE_COMPILE_OPTIONS "${_quiche_CFLAGS}" + INTERFACE_INCLUDE_DIRECTORIES "${_quiche_INCLUDE_DIRS}" + INTERFACE_LINK_DIRECTORIES "${_quiche_LIBRARY_DIRS}" + INTERFACE_LINK_LIBRARIES "${_quiche_LIBRARIES}") + endif() +endif() diff --git a/CMake/FindRustls.cmake b/CMake/FindRustls.cmake index 564b08ce15bc..270e99c6d5c7 100644 --- a/CMake/FindRustls.cmake +++ b/CMake/FindRustls.cmake @@ -25,34 +25,31 @@ # # Input variables: # -# - `RUSTLS_INCLUDE_DIR`: The Rustls include directory. -# - `RUSTLS_LIBRARY`: Path to `rustls` library. +# - `RUSTLS_INCLUDE_DIR`: Absolute path to Rustls include directory. +# - `RUSTLS_LIBRARY`: Absolute path to `rustls` library. # -# Result variables: +# Defines: # -# - `RUSTLS_FOUND`: System has Rustls. -# - `RUSTLS_INCLUDE_DIRS`: The Rustls include directories. -# - `RUSTLS_LIBRARIES`: The Rustls library names. -# - `RUSTLS_LIBRARY_DIRS`: The Rustls library directories. -# - `RUSTLS_PC_REQUIRES`: The Rustls pkg-config packages. -# - `RUSTLS_CFLAGS`: Required compiler flags. -# - `RUSTLS_VERSION`: Version of Rustls. +# - `RUSTLS_FOUND`: System has Rustls. +# - `RUSTLS_VERSION`: Version of Rustls. +# - `CURL::rustls`: Rustls library target. -set(RUSTLS_PC_REQUIRES "rustls") +set(_rustls_pc_requires "rustls") if(CURL_USE_PKGCONFIG AND NOT DEFINED RUSTLS_INCLUDE_DIR AND NOT DEFINED RUSTLS_LIBRARY) find_package(PkgConfig QUIET) - pkg_check_modules(RUSTLS ${RUSTLS_PC_REQUIRES}) + pkg_check_modules(_rustls ${_rustls_pc_requires}) endif() -if(RUSTLS_FOUND) +if(_rustls_FOUND) set(Rustls_FOUND TRUE) - string(REPLACE ";" " " RUSTLS_CFLAGS "${RUSTLS_CFLAGS}") - message(STATUS "Found Rustls (via pkg-config): ${RUSTLS_INCLUDE_DIRS} (found version \"${RUSTLS_VERSION}\")") + set(RUSTLS_FOUND TRUE) + set(RUSTLS_VERSION ${_rustls_VERSION}) + message(STATUS "Found Rustls (via pkg-config): ${_rustls_INCLUDE_DIRS} (found version \"${RUSTLS_VERSION}\")") else() - set(RUSTLS_PC_REQUIRES "") # Depend on pkg-config only when found via pkg-config + set(_rustls_pc_requires "") # Depend on pkg-config only when found via pkg-config find_path(RUSTLS_INCLUDE_DIR NAMES "rustls.h") find_library(RUSTLS_LIBRARY NAMES "rustls") @@ -65,8 +62,8 @@ else() ) if(RUSTLS_FOUND) - set(RUSTLS_INCLUDE_DIRS ${RUSTLS_INCLUDE_DIR}) - set(RUSTLS_LIBRARIES ${RUSTLS_LIBRARY}) + set(_rustls_INCLUDE_DIRS ${RUSTLS_INCLUDE_DIR}) + set(_rustls_LIBRARIES ${RUSTLS_LIBRARY}) endif() mark_as_advanced(RUSTLS_INCLUDE_DIR RUSTLS_LIBRARY) @@ -79,31 +76,45 @@ if(RUSTLS_FOUND) if(NOT SECURITY_FRAMEWORK) message(FATAL_ERROR "Security framework not found") endif() - list(APPEND RUSTLS_LIBRARIES "-framework Security") + list(APPEND _rustls_LIBRARIES "-framework Security") find_library(FOUNDATION_FRAMEWORK NAMES "Foundation") mark_as_advanced(FOUNDATION_FRAMEWORK) if(NOT FOUNDATION_FRAMEWORK) message(FATAL_ERROR "Foundation framework not found") endif() - list(APPEND RUSTLS_LIBRARIES "-framework Foundation") + list(APPEND _rustls_LIBRARIES "-framework Foundation") elseif(NOT WIN32) find_library(PTHREAD_LIBRARY NAMES "pthread") if(PTHREAD_LIBRARY) - list(APPEND RUSTLS_LIBRARIES ${PTHREAD_LIBRARY}) + list(APPEND _rustls_LIBRARIES ${PTHREAD_LIBRARY}) endif() mark_as_advanced(PTHREAD_LIBRARY) find_library(DL_LIBRARY NAMES "dl") if(DL_LIBRARY) - list(APPEND RUSTLS_LIBRARIES ${DL_LIBRARY}) + list(APPEND _rustls_LIBRARIES ${DL_LIBRARY}) endif() mark_as_advanced(DL_LIBRARY) find_library(MATH_LIBRARY NAMES "m") if(MATH_LIBRARY) - list(APPEND RUSTLS_LIBRARIES ${MATH_LIBRARY}) + list(APPEND _rustls_LIBRARIES ${MATH_LIBRARY}) endif() mark_as_advanced(MATH_LIBRARY) endif() + + if(CMAKE_VERSION VERSION_LESS 3.13) + link_directories(${_rustls_LIBRARY_DIRS}) + endif() + + if(NOT TARGET CURL::rustls) + add_library(CURL::rustls INTERFACE IMPORTED) + set_target_properties(CURL::rustls PROPERTIES + INTERFACE_LIBCURL_PC_MODULES "${_rustls_pc_requires}" + INTERFACE_COMPILE_OPTIONS "${_rustls_CFLAGS}" + INTERFACE_INCLUDE_DIRECTORIES "${_rustls_INCLUDE_DIRS}" + INTERFACE_LINK_DIRECTORIES "${_rustls_LIBRARY_DIRS}" + INTERFACE_LINK_LIBRARIES "${_rustls_LIBRARIES}") + endif() endif() diff --git a/CMake/FindWolfSSL.cmake b/CMake/FindWolfSSL.cmake index 87b640a1f23d..3a3c05f0fd03 100644 --- a/CMake/FindWolfSSL.cmake +++ b/CMake/FindWolfSSL.cmake @@ -25,18 +25,14 @@ # # Input variables: # -# - `WOLFSSL_INCLUDE_DIR`: The wolfSSL include directory. -# - `WOLFSSL_LIBRARY`: Path to `wolfssl` library. +# - `WOLFSSL_INCLUDE_DIR`: Absolute path to wolfSSL include directory. +# - `WOLFSSL_LIBRARY`: Absolute path to `wolfssl` library. # -# Result variables: +# Defines: # -# - `WOLFSSL_FOUND`: System has wolfSSL. -# - `WOLFSSL_INCLUDE_DIRS`: The wolfSSL include directories. -# - `WOLFSSL_LIBRARIES`: The wolfSSL library names. -# - `WOLFSSL_LIBRARY_DIRS`: The wolfSSL library directories. -# - `WOLFSSL_PC_REQUIRES`: The wolfSSL pkg-config packages. -# - `WOLFSSL_CFLAGS`: Required compiler flags. -# - `WOLFSSL_VERSION`: Version of wolfSSL. +# - `WOLFSSL_FOUND`: System has wolfSSL. +# - `WOLFSSL_VERSION`: Version of wolfSSL. +# - `CURL::wolfssl`: wolfSSL library target. if(DEFINED WolfSSL_INCLUDE_DIR AND NOT DEFINED WOLFSSL_INCLUDE_DIR) message(WARNING "WolfSSL_INCLUDE_DIR is deprecated, use WOLFSSL_INCLUDE_DIR instead.") @@ -47,19 +43,20 @@ if(DEFINED WolfSSL_LIBRARY AND NOT DEFINED WOLFSSL_LIBRARY) set(WOLFSSL_LIBRARY "${WolfSSL_LIBRARY}") endif() -set(WOLFSSL_PC_REQUIRES "wolfssl") +set(_wolfssl_pc_requires "wolfssl") if(CURL_USE_PKGCONFIG AND NOT DEFINED WOLFSSL_INCLUDE_DIR AND NOT DEFINED WOLFSSL_LIBRARY) find_package(PkgConfig QUIET) - pkg_check_modules(WOLFSSL ${WOLFSSL_PC_REQUIRES}) + pkg_check_modules(_wolfssl ${_wolfssl_pc_requires}) endif() -if(WOLFSSL_FOUND) +if(_wolfssl_FOUND) set(WolfSSL_FOUND TRUE) - string(REPLACE ";" " " WOLFSSL_CFLAGS "${WOLFSSL_CFLAGS}") - message(STATUS "Found WolfSSL (via pkg-config): ${WOLFSSL_INCLUDE_DIRS} (found version \"${WOLFSSL_VERSION}\")") + set(WOLFSSL_FOUND TRUE) + set(WOLFSSL_VERSION ${_wolfssl_VERSION}) + message(STATUS "Found WolfSSL (via pkg-config): ${_wolfssl_INCLUDE_DIRS} (found version \"${WOLFSSL_VERSION}\")") else() find_path(WOLFSSL_INCLUDE_DIR NAMES "wolfssl/ssl.h") find_library(WOLFSSL_LIBRARY NAMES "wolfssl") @@ -84,8 +81,8 @@ else() ) if(WOLFSSL_FOUND) - set(WOLFSSL_INCLUDE_DIRS ${WOLFSSL_INCLUDE_DIR}) - set(WOLFSSL_LIBRARIES ${WOLFSSL_LIBRARY}) + set(_wolfssl_INCLUDE_DIRS ${WOLFSSL_INCLUDE_DIR}) + set(_wolfssl_LIBRARIES ${WOLFSSL_LIBRARY}) endif() mark_as_advanced(WOLFSSL_INCLUDE_DIR WOLFSSL_LIBRARY) @@ -98,19 +95,35 @@ if(WOLFSSL_FOUND) if(NOT SECURITY_FRAMEWORK) message(FATAL_ERROR "Security framework not found") endif() - list(APPEND WOLFSSL_LIBRARIES "-framework Security") + list(APPEND _wolfssl_LIBRARIES "-framework Security") find_library(COREFOUNDATION_FRAMEWORK NAMES "CoreFoundation") mark_as_advanced(COREFOUNDATION_FRAMEWORK) if(NOT COREFOUNDATION_FRAMEWORK) message(FATAL_ERROR "CoreFoundation framework not found") endif() - list(APPEND WOLFSSL_LIBRARIES "-framework CoreFoundation") - elseif(NOT WIN32) + list(APPEND _wolfssl_LIBRARIES "-framework CoreFoundation") + elseif(WIN32) + list(APPEND _wolfssl_LIBRARIES "crypt32") + else() find_library(MATH_LIBRARY NAMES "m") if(MATH_LIBRARY) - list(APPEND WOLFSSL_LIBRARIES ${MATH_LIBRARY}) # for log and pow + list(APPEND _wolfssl_LIBRARIES ${MATH_LIBRARY}) # for log and pow endif() mark_as_advanced(MATH_LIBRARY) endif() + + if(CMAKE_VERSION VERSION_LESS 3.13) + link_directories(${_wolfssl_LIBRARY_DIRS}) + endif() + + if(NOT TARGET CURL::wolfssl) + add_library(CURL::wolfssl INTERFACE IMPORTED) + set_target_properties(CURL::wolfssl PROPERTIES + INTERFACE_LIBCURL_PC_MODULES "${_wolfssl_pc_requires}" + INTERFACE_COMPILE_OPTIONS "${_wolfssl_CFLAGS}" + INTERFACE_INCLUDE_DIRECTORIES "${_wolfssl_INCLUDE_DIRS}" + INTERFACE_LINK_DIRECTORIES "${_wolfssl_LIBRARY_DIRS}" + INTERFACE_LINK_LIBRARIES "${_wolfssl_LIBRARIES}") + endif() endif() diff --git a/CMake/FindZstd.cmake b/CMake/FindZstd.cmake index 0ea1fef46724..954a827b6fe4 100644 --- a/CMake/FindZstd.cmake +++ b/CMake/FindZstd.cmake @@ -25,18 +25,14 @@ # # Input variables: # -# - `ZSTD_INCLUDE_DIR`: The zstd include directory. -# - `ZSTD_LIBRARY`: Path to `zstd` library. +# - `ZSTD_INCLUDE_DIR`: Absolute path to zstd include directory. +# - `ZSTD_LIBRARY`: Absolute path to `zstd` library. # -# Result variables: +# Defines: # -# - `ZSTD_FOUND`: System has zstd. -# - `ZSTD_INCLUDE_DIRS`: The zstd include directories. -# - `ZSTD_LIBRARIES`: The zstd library names. -# - `ZSTD_LIBRARY_DIRS`: The zstd library directories. -# - `ZSTD_PC_REQUIRES`: The zstd pkg-config packages. -# - `ZSTD_CFLAGS`: Required compiler flags. -# - `ZSTD_VERSION`: Version of zstd. +# - `ZSTD_FOUND`: System has zstd. +# - `ZSTD_VERSION`: Version of zstd. +# - `CURL::zstd`: zstd library target. if(DEFINED Zstd_INCLUDE_DIR AND NOT DEFINED ZSTD_INCLUDE_DIR) message(WARNING "Zstd_INCLUDE_DIR is deprecated, use ZSTD_INCLUDE_DIR instead.") @@ -47,19 +43,20 @@ if(DEFINED Zstd_LIBRARY AND NOT DEFINED ZSTD_LIBRARY) set(ZSTD_LIBRARY "${Zstd_LIBRARY}") endif() -set(ZSTD_PC_REQUIRES "libzstd") +set(_zstd_pc_requires "libzstd") if(CURL_USE_PKGCONFIG AND NOT DEFINED ZSTD_INCLUDE_DIR AND NOT DEFINED ZSTD_LIBRARY) find_package(PkgConfig QUIET) - pkg_check_modules(ZSTD ${ZSTD_PC_REQUIRES}) + pkg_check_modules(_zstd ${_zstd_pc_requires}) endif() -if(ZSTD_FOUND) +if(_zstd_FOUND) set(Zstd_FOUND TRUE) - string(REPLACE ";" " " ZSTD_CFLAGS "${ZSTD_CFLAGS}") - message(STATUS "Found Zstd (via pkg-config): ${ZSTD_INCLUDE_DIRS} (found version \"${ZSTD_VERSION}\")") + set(ZSTD_FOUND TRUE) + set(ZSTD_VERSION ${_zstd_VERSION}) + message(STATUS "Found Zstd (via pkg-config): ${_zstd_INCLUDE_DIRS} (found version \"${ZSTD_VERSION}\")") else() find_path(ZSTD_INCLUDE_DIR NAMES "zstd.h") find_library(ZSTD_LIBRARY NAMES "zstd") @@ -94,9 +91,25 @@ else() ) if(ZSTD_FOUND) - set(ZSTD_INCLUDE_DIRS ${ZSTD_INCLUDE_DIR}) - set(ZSTD_LIBRARIES ${ZSTD_LIBRARY}) + set(_zstd_INCLUDE_DIRS ${ZSTD_INCLUDE_DIR}) + set(_zstd_LIBRARIES ${ZSTD_LIBRARY}) endif() mark_as_advanced(ZSTD_INCLUDE_DIR ZSTD_LIBRARY) endif() + +if(ZSTD_FOUND) + if(CMAKE_VERSION VERSION_LESS 3.13) + link_directories(${_zstd_LIBRARY_DIRS}) + endif() + + if(NOT TARGET CURL::zstd) + add_library(CURL::zstd INTERFACE IMPORTED) + set_target_properties(CURL::zstd PROPERTIES + INTERFACE_LIBCURL_PC_MODULES "${_zstd_pc_requires}" + INTERFACE_COMPILE_OPTIONS "${_zstd_CFLAGS}" + INTERFACE_INCLUDE_DIRECTORIES "${_zstd_INCLUDE_DIRS}" + INTERFACE_LINK_DIRECTORIES "${_zstd_LIBRARY_DIRS}" + INTERFACE_LINK_LIBRARIES "${_zstd_LIBRARIES}") + endif() +endif() diff --git a/CMake/Macros.cmake b/CMake/Macros.cmake index 710df701168d..80173fb03bf0 100644 --- a/CMake/Macros.cmake +++ b/CMake/Macros.cmake @@ -56,10 +56,10 @@ macro(curl_internal_test _curl_test) "${_curl_test_add_libraries}" OUTPUT_VARIABLE CURL_TEST_OUTPUT) if(${_curl_test}) - set(${_curl_test} 1 CACHE INTERNAL "Curl test") + set(${_curl_test} 1 CACHE INTERNAL "curl test") message(STATUS "Performing Test ${_curl_test} - Success") else() - set(${_curl_test} "" CACHE INTERNAL "Curl test") + set(${_curl_test} "" CACHE INTERNAL "curl test") message(STATUS "Performing Test ${_curl_test} - Failed") endif() endif() diff --git a/CMake/PickyWarnings.cmake b/CMake/PickyWarnings.cmake index bdd226e9246e..5e643c5866f9 100644 --- a/CMake/PickyWarnings.cmake +++ b/CMake/PickyWarnings.cmake @@ -29,12 +29,10 @@ set(_picky_nocheck "") # not to pass to feature checks if(CURL_WERROR) if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.24) set(CMAKE_COMPILE_WARNING_AS_ERROR ON) - else() - if(MSVC) - list(APPEND _picky_nocheck "-WX") - else() # llvm/clang and gcc style options - list(APPEND _picky_nocheck "-Werror") - endif() + elseif(MSVC) + list(APPEND _picky_nocheck "-WX") + else() # llvm/clang and gcc-style options + list(APPEND _picky_nocheck "-Werror") endif() if((CMAKE_C_COMPILER_ID STREQUAL "GNU" AND @@ -77,9 +75,15 @@ if(PICKY_COMPILER) set(_picky_enable "-W") endif() - list(APPEND _picky_enable - -Wall -pedantic - ) + list(APPEND _picky_enable "-Wall") + + if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 3.2) OR + (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 4.2) OR + CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 4.8) + list(APPEND _picky_enable "-Wpedantic") # clang 3.2 gcc 4.8 appleclang 4.2 + else() + list(APPEND _picky_enable "-pedantic") + endif() # ---------------------------------- # Add new options here, if in doubt: @@ -234,20 +238,26 @@ if(PICKY_COMPILER) -Wcast-function-type-strict # clang 16.0 appleclang 16.0 ) endif() - if(CMAKE_C_COMPILER_ID STREQUAL "Clang" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 21.0) + if((CMAKE_C_COMPILER_ID STREQUAL "Clang" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 19.1) OR + (CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 17.0)) list(APPEND _picky_enable - -Warray-compare # clang 20.0 gcc 12.0 appleclang ? - -Wc++-hidden-decl # clang 21.0 appleclang ? - -Wno-implicit-void-ptr-cast # clang 21.0 appleclang ? - -Wtentative-definition-compat # clang 21.0 appleclang ? + -Wno-format-signedness # clang 19.1 gcc 5.1 appleclang 17.0 # In clang-cl enums are signed ints by default + ) + endif() + if(CMAKE_C_COMPILER_ID STREQUAL "Clang" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 21.1) + list(APPEND _picky_enable + -Warray-compare # clang 20.1 gcc 12.0 appleclang ? + -Wc++-hidden-decl # clang 21.1 appleclang ? + -Wno-implicit-void-ptr-cast # clang 21.1 appleclang ? + -Wtentative-definition-compat # clang 21.1 appleclang ? ) if(WIN32) list(APPEND _picky_enable - -Wno-c++-keyword # clang 21.0 appleclang ? # `wchar_t` triggers it on Windows + -Wno-c++-keyword # clang 21.1 appleclang ? # `wchar_t` triggers it on Windows ) else() list(APPEND _picky_enable - -Wc++-keyword # clang 21.0 appleclang ? + -Wc++-keyword # clang 21.1 appleclang ? ) endif() endif() @@ -284,6 +294,7 @@ if(PICKY_COMPILER) if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 5.0) list(APPEND _picky_enable -Warray-bounds=2 # clang 3.0 gcc 5.0 (clang default: -Warray-bounds) + -Wno-format-signedness # clang 19.1 gcc 5.1 appleclang 17.0 ) endif() if(CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 6.0) diff --git a/CMake/Utilities.cmake b/CMake/Utilities.cmake index 335713c84cfe..efa28b75155b 100644 --- a/CMake/Utilities.cmake +++ b/CMake/Utilities.cmake @@ -59,6 +59,7 @@ function(curl_dumptargetprops _target) string(REPLACE "\n" ";" _cmake_property_list "${_cmake_property_list}") list(REMOVE_DUPLICATES _cmake_property_list) list(REMOVE_ITEM _cmake_property_list "") + list(APPEND _cmake_property_list "INTERFACE_LIBCURL_PC_MODULES") foreach(_prop IN LISTS _cmake_property_list) if(_prop MATCHES "") foreach(_config IN ITEMS "DEBUG" "RELEASE" "MINSIZEREL" "RELWITHDEBINFO") diff --git a/CMake/cmake_uninstall.cmake.in b/CMake/cmake_uninstall.in.cmake similarity index 100% rename from CMake/cmake_uninstall.cmake.in rename to CMake/cmake_uninstall.in.cmake diff --git a/CMake/curl-config.cmake.in b/CMake/curl-config.cmake.in deleted file mode 100644 index d1582b8d41b9..000000000000 --- a/CMake/curl-config.cmake.in +++ /dev/null @@ -1,77 +0,0 @@ -#*************************************************************************** -# _ _ ____ _ -# Project ___| | | | _ \| | -# / __| | | | |_) | | -# | (__| |_| | _ <| |___ -# \___|\___/|_| \_\_____| -# -# Copyright (C) Daniel Stenberg, , et al. -# -# This software is licensed as described in the file COPYING, which -# you should have received as part of this distribution. The terms -# are also available at https://curl.se/docs/copyright.html. -# -# You may opt to use, copy, modify, merge, publish, distribute and/or sell -# copies of the Software, and permit persons to whom the Software is -# furnished to do so, under the terms of the COPYING file. -# -# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY -# KIND, either express or implied. -# -# SPDX-License-Identifier: curl -# -########################################################################### -@PACKAGE_INIT@ - -include(CMakeFindDependencyMacro) -if("@USE_OPENSSL@") - if("@OPENSSL_VERSION_MAJOR@") - find_dependency(OpenSSL "@OPENSSL_VERSION_MAJOR@") - else() - find_dependency(OpenSSL) - endif() -endif() -if("@HAVE_LIBZ@") - find_dependency(ZLIB "@ZLIB_VERSION_MAJOR@") -endif() - -include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake") - -# Alias for either shared or static library -if(NOT TARGET @PROJECT_NAME@::@LIB_NAME@) - if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.11 AND CMAKE_VERSION VERSION_LESS 3.18) - set_target_properties(@PROJECT_NAME@::@LIB_SELECTED@ PROPERTIES IMPORTED_GLOBAL TRUE) - endif() - add_library(@PROJECT_NAME@::@LIB_NAME@ ALIAS @PROJECT_NAME@::@LIB_SELECTED@) -endif() - -# For compatibility with CMake's FindCURL.cmake -set(CURL_VERSION_STRING "@CURLVERSION@") -set(CURL_LIBRARIES @PROJECT_NAME@::@LIB_NAME@) -set_and_check(CURL_INCLUDE_DIRS "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@") - -set(CURL_SUPPORTED_PROTOCOLS "@CURL_SUPPORTED_PROTOCOLS_LIST@") -set(CURL_SUPPORTED_FEATURES "@CURL_SUPPORTED_FEATURES_LIST@") - -foreach(_item IN LISTS CURL_SUPPORTED_PROTOCOLS CURL_SUPPORTED_FEATURES) - set(CURL_SUPPORTS_${_item} TRUE) -endforeach() - -set(_missing_req "") -foreach(_item IN LISTS CURL_FIND_COMPONENTS) - if(CURL_SUPPORTS_${_item}) - set(CURL_${_item}_FOUND TRUE) - elseif(CURL_FIND_REQUIRED_${_item}) - list(APPEND _missing_req ${_item}) - endif() -endforeach() - -if(_missing_req) - string(REPLACE ";" " " _missing_req "${_missing_req}") - if(CURL_FIND_REQUIRED) - message(FATAL_ERROR "CURL: missing required components: ${_missing_req}") - endif() - unset(_missing_req) -endif() - -check_required_components("@PROJECT_NAME@") diff --git a/CMake/curl-config.in.cmake b/CMake/curl-config.in.cmake new file mode 100644 index 000000000000..7f346c832ca5 --- /dev/null +++ b/CMake/curl-config.in.cmake @@ -0,0 +1,207 @@ +#*************************************************************************** +# _ _ ____ _ +# Project ___| | | | _ \| | +# / __| | | | |_) | | +# | (__| |_| | _ <| |___ +# \___|\___/|_| \_\_____| +# +# Copyright (C) Daniel Stenberg, , et al. +# +# This software is licensed as described in the file COPYING, which +# you should have received as part of this distribution. The terms +# are also available at https://curl.se/docs/copyright.html. +# +# You may opt to use, copy, modify, merge, publish, distribute and/or sell +# copies of the Software, and permit persons to whom the Software is +# furnished to do so, under the terms of the COPYING file. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. +# +# SPDX-License-Identifier: curl +# +########################################################################### +@PACKAGE_INIT@ + +option(CURL_USE_PKGCONFIG "Enable pkg-config to detect @PROJECT_NAME@ dependencies. Default: @CURL_USE_PKGCONFIG@" + "@CURL_USE_PKGCONFIG@") + +if(CMAKE_VERSION VERSION_LESS @CMAKE_MINIMUM_REQUIRED_VERSION@) + message(STATUS "@PROJECT_NAME@: @PROJECT_NAME@-specific Find modules require " + "CMake @CMAKE_MINIMUM_REQUIRED_VERSION@ or upper, found: ${CMAKE_VERSION}.") +endif() + +include(CMakeFindDependencyMacro) + +if("@USE_OPENSSL@") + if("@OPENSSL_VERSION_MAJOR@") + find_dependency(OpenSSL "@OPENSSL_VERSION_MAJOR@") + else() + find_dependency(OpenSSL) + endif() +endif() +if("@HAVE_LIBZ@") + find_dependency(ZLIB "@ZLIB_VERSION_MAJOR@") +endif() + +set(_curl_cmake_module_path_save ${CMAKE_MODULE_PATH}) +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR} ${CMAKE_MODULE_PATH}) + +set(_curl_libs "") + +if("@HAVE_BROTLI@") + find_dependency(Brotli) + list(APPEND _curl_libs CURL::brotli) +endif() +if("@USE_ARES@") + find_dependency(Cares) + list(APPEND _curl_libs CURL::cares) +endif() +if("@HAVE_GSSAPI@") + find_dependency(GSS) + list(APPEND _curl_libs CURL::gss) +endif() +if("@USE_BACKTRACE@") + find_dependency(Libbacktrace) + list(APPEND _curl_libs CURL::libbacktrace) +endif() +if("@USE_GSASL@") + find_dependency(Libgsasl) + list(APPEND _curl_libs CURL::libgsasl) +endif() +if(NOT "@USE_WIN32_LDAP@" AND NOT "@CURL_DISABLE_LDAP@") + find_dependency(LDAP) + list(APPEND _curl_libs CURL::ldap) +endif() +if("@HAVE_LIBIDN2@") + find_dependency(Libidn2) + list(APPEND _curl_libs CURL::libidn2) +endif() +if("@USE_LIBPSL@") + find_dependency(Libpsl) + list(APPEND _curl_libs CURL::libpsl) +endif() +if("@USE_LIBRTMP@") + find_dependency(Librtmp) + list(APPEND _curl_libs CURL::librtmp) +endif() +if("@USE_LIBSSH@") + find_dependency(Libssh) + list(APPEND _curl_libs CURL::libssh) +endif() +if("@USE_LIBSSH2@") + find_dependency(Libssh2) + list(APPEND _curl_libs CURL::libssh2) +endif() +if("@USE_LIBUV@") + find_dependency(Libuv) + list(APPEND _curl_libs CURL::libuv) +endif() +if("@USE_MBEDTLS@") + find_dependency(MbedTLS) + list(APPEND _curl_libs CURL::mbedtls) +endif() +if("@USE_NGHTTP2@") + find_dependency(NGHTTP2) + list(APPEND _curl_libs CURL::nghttp2) +endif() +if("@USE_NGHTTP3@") + find_dependency(NGHTTP3) + list(APPEND _curl_libs CURL::nghttp3) +endif() +if("@USE_NGTCP2@") + find_dependency(NGTCP2) + list(APPEND _curl_libs CURL::ngtcp2) +endif() +if("@USE_GNUTLS@") + find_dependency(GnuTLS) + list(APPEND _curl_libs CURL::gnutls) + find_dependency(Nettle) + list(APPEND _curl_libs CURL::nettle) +endif() +if("@USE_QUICHE@") + find_dependency(Quiche) + list(APPEND _curl_libs CURL::quiche) +endif() +if("@USE_RUSTLS@") + find_dependency(Rustls) + list(APPEND _curl_libs CURL::rustls) +endif() +if("@USE_WOLFSSL@") + find_dependency(WolfSSL) + list(APPEND _curl_libs CURL::wolfssl) +endif() +if("@HAVE_ZSTD@") + find_dependency(Zstd) + list(APPEND _curl_libs CURL::zstd) +endif() + +set(CMAKE_MODULE_PATH ${_curl_cmake_module_path_save}) + +if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND WIN32 AND NOT TARGET CURL::win32_winsock) + add_library(CURL::win32_winsock INTERFACE IMPORTED) + set_target_properties(CURL::win32_winsock PROPERTIES INTERFACE_LINK_LIBRARIES "ws2_32") +endif() + +include("${CMAKE_CURRENT_LIST_DIR}/@TARGETS_EXPORT_NAME@.cmake") + +# Alias for either shared or static library +if(NOT TARGET @PROJECT_NAME@::@LIB_NAME@) + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.11 AND CMAKE_VERSION VERSION_LESS 3.18) + set_target_properties(@PROJECT_NAME@::@LIB_SELECTED@ PROPERTIES IMPORTED_GLOBAL TRUE) + endif() + add_library(@PROJECT_NAME@::@LIB_NAME@ ALIAS @PROJECT_NAME@::@LIB_SELECTED@) +endif() + +if(TARGET @PROJECT_NAME@::@LIB_STATIC@) + # CMake before CMP0099 (CMake 3.17 2020-03-20) did not propagate libdirs to + # targets. It expected libs to have an absolute filename. As a workaround, + # manually apply dependency libdirs, for CMake consumers without this policy. + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.17) + cmake_policy(GET CMP0099 _has_CMP0099) # https://cmake.org/cmake/help/latest/policy/CMP0099.html + endif() + if(NOT _has_CMP0099 AND CMAKE_VERSION VERSION_GREATER_EQUAL 3.13 AND _curl_libs) + set(_curl_libdirs "") + foreach(_curl_lib IN LISTS _curl_libs) + get_target_property(_curl_libdir "${_curl_lib}" INTERFACE_LINK_DIRECTORIES) + if(_curl_libdir) + list(APPEND _curl_libdirs "${_curl_libdir}") + endif() + endforeach() + if(_curl_libdirs) + target_link_directories(@PROJECT_NAME@::@LIB_STATIC@ INTERFACE ${_curl_libdirs}) + endif() + endif() +endif() + +# For compatibility with CMake's FindCURL.cmake +set(CURL_VERSION_STRING "@CURLVERSION@") +set(CURL_LIBRARIES @PROJECT_NAME@::@LIB_NAME@) +set(CURL_LIBRARIES_PRIVATE "@LIBCURL_PC_LIBS_PRIVATE_LIST@") +set_and_check(CURL_INCLUDE_DIRS "@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@") + +set(CURL_SUPPORTED_PROTOCOLS "@CURL_SUPPORTED_PROTOCOLS_LIST@") +set(CURL_SUPPORTED_FEATURES "@CURL_SUPPORTED_FEATURES_LIST@") + +foreach(_curl_item IN LISTS CURL_SUPPORTED_PROTOCOLS CURL_SUPPORTED_FEATURES) + set(CURL_SUPPORTS_${_curl_item} TRUE) +endforeach() + +set(_curl_missing_req "") +foreach(_curl_item IN LISTS CURL_FIND_COMPONENTS) + if(CURL_SUPPORTS_${_curl_item}) + set(CURL_${_curl_item}_FOUND TRUE) + elseif(CURL_FIND_REQUIRED_${_curl_item}) + list(APPEND _curl_missing_req ${_curl_item}) + endif() +endforeach() + +if(_curl_missing_req) + string(REPLACE ";" " " _curl_missing_req "${_curl_missing_req}") + if(CURL_FIND_REQUIRED) + message(FATAL_ERROR "@PROJECT_NAME@: missing required components: ${_curl_missing_req}") + endif() + unset(_curl_missing_req) +endif() + +check_required_components("@PROJECT_NAME@") diff --git a/CMake/unix-cache.cmake b/CMake/unix-cache.cmake index 2c85626a4957..f3db9f0e974c 100644 --- a/CMake/unix-cache.cmake +++ b/CMake/unix-cache.cmake @@ -142,7 +142,7 @@ set(HAVE_GETRLIMIT 1) set(HAVE_GETSOCKNAME 1) set(HAVE_GETTIMEOFDAY 1) if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - set(HAVE_GLIBC_STRERROR_R 1) + # Depends on C library. else() set(HAVE_GLIBC_STRERROR_R 0) endif() @@ -164,11 +164,12 @@ else() endif() set(HAVE_LIBGEN_H 1) if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - set(HAVE_LINUX_TCP_H 1) + # Requires Linux kernel userspace headers. Expected with glibc. May be missing by default with MUSL. else() set(HAVE_LINUX_TCP_H 0) endif() set(HAVE_LOCALE_H 1) +set(HAVE_LOCALTIME_R 1) set(HAVE_LONGLONG 1) if(APPLE) set(HAVE_MACH_ABSOLUTE_TIME 1) @@ -204,7 +205,7 @@ endif() set(HAVE_POLL 1) set(HAVE_POLL_H 1) if(CMAKE_SYSTEM_NAME STREQUAL "Linux") - set(HAVE_POSIX_STRERROR_R 0) + # Depends on C library. else() set(HAVE_POSIX_STRERROR_R 1) endif() diff --git a/CMake/win32-cache.cmake b/CMake/win32-cache.cmake index 8cb9b58b3937..e704d2195b6f 100644 --- a/CMake/win32-cache.cmake +++ b/CMake/win32-cache.cmake @@ -53,11 +53,7 @@ else() if(MSVC) set(HAVE_UNISTD_H 0) set(HAVE_STDDEF_H 1) # detected by CMake internally in check_type_size() - if(MSVC_VERSION GREATER_EQUAL 1600) - set(HAVE_STDINT_H 1) # detected by CMake internally in check_type_size() - else() - set(HAVE_STDINT_H 0) # detected by CMake internally in check_type_size() - endif() + set(HAVE_STDINT_H 1) # detected by CMake internally in check_type_size() if(MSVC_VERSION GREATER_EQUAL 1800) set(HAVE_STDBOOL_H 1) else() @@ -127,6 +123,7 @@ set(HAVE_IOCTL_SIOCGIFADDR 0) set(HAVE_IO_H 1) set(HAVE_LINUX_TCP_H 0) set(HAVE_LOCALE_H 1) +set(HAVE_LOCALTIME_R 0) set(HAVE_MEMRCHR 0) set(HAVE_MSG_NOSIGNAL 0) set(HAVE_NETDB_H 0) @@ -193,7 +190,7 @@ if(MINGW OR MSVC) curl_prefill_type_size("CURL_OFF_T" 8) curl_prefill_type_size("CURL_SOCKET_T" ${CMAKE_SIZEOF_VOID_P}) curl_prefill_type_size("SIZE_T" ${CMAKE_SIZEOF_VOID_P}) - # TIME_T: 8 for _WIN64 or UCRT or MSVC and not Windows CE, 4 otherwise + # TIME_T: 8 for _WIN64 or UCRT or MSVC, 4 otherwise # Also 4 for non-UCRT 32-bit when _USE_32BIT_TIME_T is set. # mingw-w64 sets _USE_32BIT_TIME_T unless __MINGW_USE_VC2005_COMPAT is explicit defined. if(MSVC) @@ -206,25 +203,3 @@ if(MINGW OR MSVC) curl_prefill_type_size("OFF_T" 8) # mingw-w64 v3+ endif() endif() - -# Windows CE exceptions - -if(WINCE) - set(HAVE_FREEADDRINFO 0) - set(HAVE_GETADDRINFO 0) - set(HAVE_LOCALE_H 0) - set(HAVE_SETLOCALE 0) - set(HAVE_SETMODE 0) - set(HAVE_SIGNAL 0) - set(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID 0) - curl_prefill_type_size("CURL_SOCKET_T" 4) - curl_prefill_type_size("TIME_T" 4) - curl_prefill_type_size("SIZE_T" 4) - if(MINGW32CE) - set(HAVE_STRTOK_R 0) - set(HAVE__SETMODE 0) - set(HAVE_FILE_OFFSET_BITS 0) - curl_prefill_type_size("SSIZE_T" 4) - curl_prefill_type_size("OFF_T" 4) - endif() -endif() diff --git a/CMakeLists.txt b/CMakeLists.txt index 65eaaf670a5e..43ec013508c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,6 @@ # SPDX-License-Identifier: curl # ########################################################################### -# by Tetetest and Sukender (Benoit Neil) cmake_minimum_required(VERSION 3.7...3.16 FATAL_ERROR) message(STATUS "Using CMake version ${CMAKE_VERSION}") @@ -67,41 +66,10 @@ project(CURL LANGUAGES C) # CMake does not recognize some targets accurately. Touch up configuration manually as a workaround. -if(WINDOWS_STORE AND MINGW) # mingw UWP build +if(WINDOWS_STORE AND MINGW) # MinGW UWP build # CMake (as of v3.31.2) gets confused and applies the MSVC rc.exe command-line - # template to windres. Reset it to the windres template via 'Modules/Platform/Windows-windres.cmake': + # template to windres. Reset it to the windres template as in 'Modules/Platform/Windows-windres.cmake': set(CMAKE_RC_COMPILE_OBJECT " -O coff ") -elseif(WIN32 AND WINCE AND CMAKE_C_COMPILER_ID STREQUAL "GNU") # mingw32ce build - if(NOT MINGW32CE_LIBRARY_DIR) - message(FATAL_ERROR "Set MINGW32CE_LIBRARY_DIR variable to the mingw32ce platform library directory.") - endif() - - set(MINGW 1) - set(MINGW32CE 1) - - # Build implib with libcurl DLL. Copied from CMake's 'Modules/Platform/Windows-GNU.cmake'. - set(CMAKE_C_CREATE_SHARED_LIBRARY " ") - string(APPEND CMAKE_C_CREATE_SHARED_LIBRARY " -o -Wl,--out-implib,") - string(APPEND CMAKE_C_CREATE_SHARED_LIBRARY " ${CMAKE_GNULD_IMAGE_VERSION} ") - - # Build resources. Copied from CMake's 'Modules/Platform/Windows-windres.cmake'. - set(CMAKE_RC_COMPILE_OBJECT " -O coff ") - enable_language(RC) - - # To compile long long integer literals - set_property(DIRECTORY APPEND PROPERTY COMPILE_OPTIONS "-std=gnu99") - string(APPEND CMAKE_REQUIRED_FLAGS " -std=gnu99") - - set(CMAKE_C_COMPILE_OPTIONS_PIC "") # CMake sets it to '-fPIC', confusing the toolchain and breaking builds. Zap it. - - set(CMAKE_STATIC_LIBRARY_PREFIX "lib") - set(CMAKE_STATIC_LIBRARY_SUFFIX ".a") - set(CMAKE_SHARED_LIBRARY_PREFIX "lib") - set(CMAKE_SHARED_LIBRARY_SUFFIX ".dll") - set(CMAKE_IMPORT_LIBRARY_PREFIX "lib") - set(CMAKE_IMPORT_LIBRARY_SUFFIX ".dll.a") - set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "") - set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll.a" ".a" ".lib") elseif(DOS AND CMAKE_C_COMPILER_ID STREQUAL "GNU") # DJGPP set(CMAKE_STATIC_LIBRARY_PREFIX "lib") set(CMAKE_STATIC_LIBRARY_SUFFIX ".a") @@ -130,9 +98,6 @@ endif() if(WIN32) string(APPEND _target_flags " WIN32") endif() -if(WINCE) - string(APPEND _target_flags " WINCE") -endif() if(WINDOWS_STORE) string(APPEND _target_flags " UWP") endif() @@ -204,7 +169,8 @@ endif() option(CURL_WERROR "Turn compiler warnings into errors" OFF) option(PICKY_COMPILER "Enable picky compiler options" ON) option(BUILD_CURL_EXE "Build curl executable" ON) -option(BUILD_SHARED_LIBS "Build shared libraries" ON) +get_property(_has_shared GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS) +option(BUILD_SHARED_LIBS "Build shared libraries" ${_has_shared}) option(BUILD_STATIC_LIBS "Build static libraries" OFF) option(BUILD_STATIC_CURL "Build curl executable with static libcurl" OFF) option(ENABLE_ARES "Enable c-ares support" OFF) @@ -212,12 +178,12 @@ option(CURL_DISABLE_INSTALL "Disable installation targets" OFF) if(WIN32) option(ENABLE_UNICODE "Use the Unicode version of the Windows API functions" OFF) - if(WINDOWS_STORE OR WINCE) + if(WINDOWS_STORE) set(ENABLE_UNICODE ON) endif() if(ENABLE_UNICODE) set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS "UNICODE" "_UNICODE") - if(MINGW AND NOT MINGW32CE) + if(MINGW) set_property(DIRECTORY APPEND PROPERTY COMPILE_OPTIONS "-municode") endif() endif() @@ -260,7 +226,7 @@ if(WIN32) endif() unset(MINGW64_VERSION CACHE) # Avoid storing in CMake cache endif() -elseif(DOS OR AMIGA) +elseif(DOS) set(BUILD_SHARED_LIBS OFF) set(BUILD_STATIC_LIBS ON) endif() @@ -300,6 +266,7 @@ endif() option(CURL_CLANG_TIDY "Run the build through clang-tidy" OFF) if(CURL_CLANG_TIDY) set(CMAKE_UNITY_BUILD OFF) # clang-tidy is not looking into #included sources, thus not compatible with unity builds. + set(CURL_DISABLE_TYPECHECK ON) # to improve performance and avoid potential interference. set(_tidy_checks "") list(APPEND _tidy_checks "-clang-analyzer-security.insecureAPI.bzero") # for FD_ZERO() (seen on macOS) list(APPEND _tidy_checks "-clang-analyzer-security.insecureAPI.strcpy") @@ -392,23 +359,14 @@ else() endif() option(CURL_USE_PKGCONFIG "Enable pkg-config to detect dependencies" ${_curl_use_pkgconfig_default}) -# Initialize variables collecting dependency libs, paths, pkg-config names. +# Initialize variables collecting system and dependency libs. set(CURL_NETWORK_AND_TIME_LIBS "") set(CURL_LIBS "") -set(CURL_LIBDIRS "") -set(LIBCURL_PC_REQUIRES_PRIVATE "") if(ENABLE_ARES) set(USE_ARES 1) find_package(Cares REQUIRED) - list(APPEND CURL_LIBS ${CARES_LIBRARIES}) - list(APPEND CURL_LIBDIRS ${CARES_LIBRARY_DIRS}) - list(APPEND LIBCURL_PC_REQUIRES_PRIVATE ${CARES_PC_REQUIRES}) - include_directories(SYSTEM ${CARES_INCLUDE_DIRS}) - link_directories(${CARES_LIBRARY_DIRS}) - if(CARES_CFLAGS) - string(APPEND CMAKE_C_FLAGS " ${CARES_CFLAGS}") - endif() + list(APPEND CURL_LIBS CURL::cares) endif() include(CurlSymbolHiding) @@ -496,7 +454,7 @@ option(CURL_DISABLE_SMB "Disable SMB" OFF) mark_as_advanced(CURL_DISABLE_SMB) option(CURL_DISABLE_SMTP "Disable SMTP" OFF) mark_as_advanced(CURL_DISABLE_SMTP) -option(CURL_DISABLE_SOCKETPAIR "Disable use of socketpair for curl_multi_poll" OFF) +option(CURL_DISABLE_SOCKETPAIR "Disable use of socketpair for curl_multi_poll()" OFF) mark_as_advanced(CURL_DISABLE_SOCKETPAIR) option(CURL_DISABLE_WEBSOCKETS "Disable WebSocket" OFF) mark_as_advanced(CURL_DISABLE_WEBSOCKETS) @@ -504,6 +462,8 @@ option(CURL_DISABLE_TELNET "Disable Telnet" OFF) mark_as_advanced(CURL_DISABLE_TELNET) option(CURL_DISABLE_TFTP "Disable TFTP" OFF) mark_as_advanced(CURL_DISABLE_TFTP) +option(CURL_DISABLE_TYPECHECK "Disable curl_easy_setopt()/curl_easy_getinfo() type checking" OFF) +mark_as_advanced(CURL_DISABLE_TYPECHECK) option(CURL_DISABLE_VERBOSE_STRINGS "Disable verbose strings" OFF) mark_as_advanced(CURL_DISABLE_VERBOSE_STRINGS) @@ -537,7 +497,7 @@ if(HTTP_ONLY) set(CURL_DISABLE_TFTP ON) endif() -if(WINDOWS_STORE OR WINCE) +if(WINDOWS_STORE) set(CURL_DISABLE_TELNET ON) # telnet code needs fixing to compile for UWP. endif() @@ -560,7 +520,7 @@ option(BUILD_LIBCURL_DOCS "Build libcurl man pages" ON) option(BUILD_MISC_DOCS "Build misc man pages (e.g. curl-config and mk-ca-bundle)" ON) option(ENABLE_CURL_MANUAL "Build the man page for curl and enable its -M/--manual option" ON) -if((ENABLE_CURL_MANUAL OR BUILD_LIBCURL_DOCS) AND NOT PERL_FOUND) +if((ENABLE_CURL_MANUAL OR BUILD_LIBCURL_DOCS) AND NOT Perl_FOUND) message(WARNING "Perl not found. Will not build manuals.") endif() @@ -623,21 +583,7 @@ if(ENABLE_THREADED_RESOLVER) endif() # Check for all needed libraries -if(WIN32) - if(WINCE) - set(_win32_winsock "ws2") - else() - set(_win32_winsock "ws2_32") - endif() - set(_win32_crypt32 "crypt32") - set(_win32_secur32 "secur32") - - if(MINGW32CE) # FIXME upstream: must specify the full path to avoid CMake converting "ws2" to "ws2.lib" - set(_win32_winsock "${MINGW32CE_LIBRARY_DIR}/lib${_win32_winsock}.a") - set(_win32_crypt32 "${MINGW32CE_LIBRARY_DIR}/lib${_win32_crypt32}.a") - set(_win32_secur32 "${MINGW32CE_LIBRARY_DIR}/lib${_win32_secur32}.a") - endif() -elseif(DOS) +if(DOS) if(WATT_ROOT) set(USE_WATT32 ON) # FIXME upstream: must specify the full path to avoid CMake converting "watt" to "watt.lib" @@ -645,7 +591,7 @@ elseif(DOS) include_directories(SYSTEM "${WATT_ROOT}/inc") list(APPEND CMAKE_REQUIRED_INCLUDES "${WATT_ROOT}/inc") else() - message(FATAL_ERROR "Set WATT_ROOT variable to the root installation of Watt-32.") + message(FATAL_ERROR "Set WATT_ROOT variable to the absolute path to the root installation of Watt-32.") endif() elseif(AMIGA) if(AMISSL_INCLUDE_DIR AND AMISSL_STUBS_LIBRARY AND AMISSL_AUTO_LIBRARY) @@ -658,7 +604,7 @@ elseif(AMIGA) set(CURL_USE_OPENSSL ON) set(CURL_CA_FALLBACK ON CACHE BOOL "") endif() -elseif(NOT APPLE) +elseif(NOT WIN32 AND NOT APPLE) check_library_exists("socket" "connect" "" HAVE_LIBSOCKET) if(HAVE_LIBSOCKET) set(CURL_NETWORK_AND_TIME_LIBS "socket" ${CURL_NETWORK_AND_TIME_LIBS}) @@ -693,7 +639,7 @@ if(ENABLE_IPV6) endif() endif() endif() -if(ENABLE_IPV6 AND NOT WINCE) +if(ENABLE_IPV6) set(USE_IPV6 ON) endif() @@ -808,7 +754,7 @@ if(CURL_USE_OPENSSL) # Depend on OpenSSL via imported targets. This allows our dependents to # get our dependencies transitively. list(APPEND CURL_LIBS OpenSSL::SSL OpenSSL::Crypto) - list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "openssl") + set_target_properties(OpenSSL::SSL PROPERTIES INTERFACE_LIBCURL_PC_MODULES "openssl") if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "openssl") set(_valid_default_ssl_backend TRUE) @@ -855,33 +801,29 @@ if(CURL_USE_MBEDTLS) endif() set(_ssl_enabled ON) set(USE_MBEDTLS ON) - list(APPEND CURL_LIBS ${MBEDTLS_LIBRARIES}) - list(APPEND CURL_LIBDIRS ${MBEDTLS_LIBRARY_DIRS}) - list(APPEND LIBCURL_PC_REQUIRES_PRIVATE ${MBEDTLS_PC_REQUIRES}) - include_directories(SYSTEM ${MBEDTLS_INCLUDE_DIRS}) - link_directories(${MBEDTLS_LIBRARY_DIRS}) - if(MBEDTLS_CFLAGS) - string(APPEND CMAKE_C_FLAGS " ${MBEDTLS_CFLAGS}") - endif() + list(APPEND CURL_LIBS CURL::mbedtls) if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "mbedtls") set(_valid_default_ssl_backend TRUE) endif() set(_curl_ca_bundle_supported TRUE) + + if(MBEDTLS_VERSION VERSION_GREATER_EQUAL 4.0.0) + set(HAVE_MBEDTLS_DES_CRYPT_ECB 0) # pre-fill detection result + endif() + if(NOT DEFINED HAVE_MBEDTLS_DES_CRYPT_ECB) + cmake_push_check_state() + list(APPEND CMAKE_REQUIRED_LIBRARIES CURL::mbedtls) + check_function_exists("mbedtls_des_crypt_ecb" HAVE_MBEDTLS_DES_CRYPT_ECB) # in mbedTLS <4 + cmake_pop_check_state() + endif() endif() if(CURL_USE_WOLFSSL) find_package(WolfSSL REQUIRED) set(_ssl_enabled ON) set(USE_WOLFSSL ON) - list(APPEND CURL_LIBS ${WOLFSSL_LIBRARIES}) - list(APPEND CURL_LIBDIRS ${WOLFSSL_LIBRARY_DIRS}) - list(APPEND LIBCURL_PC_REQUIRES_PRIVATE ${WOLFSSL_PC_REQUIRES}) - include_directories(SYSTEM ${WOLFSSL_INCLUDE_DIRS}) - link_directories(${WOLFSSL_LIBRARY_DIRS}) - if(WOLFSSL_CFLAGS) - string(APPEND CMAKE_C_FLAGS " ${WOLFSSL_CFLAGS}") - endif() + list(APPEND CURL_LIBS CURL::wolfssl) if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "wolfssl") set(_valid_default_ssl_backend TRUE) @@ -890,31 +832,12 @@ if(CURL_USE_WOLFSSL) endif() if(CURL_USE_GNUTLS) - if(CURL_USE_PKGCONFIG) - find_package(PkgConfig QUIET) - pkg_check_modules(GNUTLS "gnutls") - if(GNUTLS_FOUND) - set(GNUTLS_LIBRARIES ${GNUTLS_LINK_LIBRARIES}) - string(REPLACE ";" " " GNUTLS_CFLAGS "${GNUTLS_CFLAGS}") - if(GNUTLS_CFLAGS) - string(APPEND CMAKE_C_FLAGS " ${GNUTLS_CFLAGS}") - endif() - endif() - endif() - if(NOT GNUTLS_FOUND) - find_package(GnuTLS REQUIRED) - endif() + find_package(GnuTLS REQUIRED) + list(APPEND CURL_LIBS CURL::gnutls) find_package(Nettle REQUIRED) + list(APPEND CURL_LIBS CURL::nettle) set(_ssl_enabled ON) set(USE_GNUTLS ON) - list(APPEND CURL_LIBS ${GNUTLS_LIBRARIES} ${NETTLE_LIBRARIES}) - list(APPEND CURL_LIBDIRS ${GNUTLS_LIBRARY_DIRS} ${NETTLE_LIBRARY_DIRS}) - list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "gnutls" ${NETTLE_PC_REQUIRES}) - include_directories(SYSTEM ${GNUTLS_INCLUDE_DIRS} ${NETTLE_INCLUDE_DIRS}) - link_directories(${NETTLE_LIBRARY_DIRS}) - if(NETTLE_CFLAGS) - string(APPEND CMAKE_C_FLAGS " ${NETTLE_CFLAGS}") - endif() if(CURL_DEFAULT_SSL_BACKEND AND CURL_DEFAULT_SSL_BACKEND STREQUAL "gnutls") set(_valid_default_ssl_backend TRUE) @@ -923,8 +846,9 @@ if(CURL_USE_GNUTLS) if(NOT DEFINED HAVE_GNUTLS_SRP AND NOT CURL_DISABLE_SRP) cmake_push_check_state() - list(APPEND CMAKE_REQUIRED_INCLUDES "${GNUTLS_INCLUDE_DIRS}") - list(APPEND CMAKE_REQUIRED_LIBRARIES "${GNUTLS_LIBRARIES}") + list(APPEND CMAKE_REQUIRED_LIBRARIES CURL::gnutls) + # In GnuTLS 3.8.0 (2023-02-10) and upper, this check always succeeds. + # Detecting actual TLS-SRP support needs poking the API at runtime. check_symbol_exists("gnutls_srp_verifier" "gnutls/gnutls.h" HAVE_GNUTLS_SRP) cmake_pop_check_state() endif() @@ -934,23 +858,14 @@ if(CURL_USE_RUSTLS) find_package(Rustls REQUIRED) set(_ssl_enabled ON) set(USE_RUSTLS ON) - list(APPEND CURL_LIBS ${RUSTLS_LIBRARIES}) - list(APPEND CURL_LIBDIRS ${RUSTLS_LIBRARY_DIRS}) - list(APPEND LIBCURL_PC_REQUIRES_PRIVATE ${RUSTLS_PC_REQUIRES}) - include_directories(SYSTEM ${RUSTLS_INCLUDE_DIRS}) - link_directories(${RUSTLS_LIBRARY_DIRS}) - if(RUSTLS_CFLAGS) - string(APPEND CMAKE_C_FLAGS " ${RUSTLS_CFLAGS}") - endif() + list(APPEND CURL_LIBS CURL::rustls) if(NOT DEFINED HAVE_RUSTLS_SUPPORTED_HPKE) if(RUSTLS_VERSION AND RUSTLS_VERSION VERSION_GREATER_EQUAL 0.15) set(HAVE_RUSTLS_SUPPORTED_HPKE TRUE) elseif(NOT RUSTLS_VERSION) cmake_push_check_state() - list(APPEND CMAKE_REQUIRED_INCLUDES "${RUSTLS_INCLUDE_DIRS}") - list(APPEND CMAKE_REQUIRED_LIBRARIES "${RUSTLS_LIBRARIES}") - curl_required_libpaths("${RUSTLS_LIBRARY_DIRS}") + list(APPEND CMAKE_REQUIRED_LIBRARIES CURL::rustls) check_symbol_exists("rustls_supported_hpke" "rustls.h" HAVE_RUSTLS_SUPPORTED_HPKE) cmake_pop_check_state() endif() @@ -979,21 +894,14 @@ if(ZLIB_FOUND) # Depend on ZLIB via imported targets. This allows our dependents to # get our dependencies transitively. list(APPEND CURL_LIBS ZLIB::ZLIB) - list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "zlib") + set_target_properties(ZLIB::ZLIB PROPERTIES INTERFACE_LIBCURL_PC_MODULES "zlib") endif() set(HAVE_BROTLI OFF) curl_dependency_option(CURL_BROTLI Brotli "brotli") if(BROTLI_FOUND) set(HAVE_BROTLI ON) - list(APPEND CURL_LIBS ${BROTLI_LIBRARIES}) - list(APPEND CURL_LIBDIRS ${BROTLI_LIBRARY_DIRS}) - list(APPEND LIBCURL_PC_REQUIRES_PRIVATE ${BROTLI_PC_REQUIRES}) - include_directories(SYSTEM ${BROTLI_INCLUDE_DIRS}) - link_directories(${BROTLI_LIBRARY_DIRS}) - if(BROTLI_CFLAGS) - string(APPEND CMAKE_C_FLAGS " ${BROTLI_CFLAGS}") - endif() + list(APPEND CURL_LIBS CURL::brotli) endif() set(HAVE_ZSTD OFF) @@ -1001,14 +909,7 @@ curl_dependency_option(CURL_ZSTD Zstd "zstd") if(ZSTD_FOUND) if(ZSTD_VERSION VERSION_GREATER_EQUAL 1.0.0) set(HAVE_ZSTD ON) - list(APPEND CURL_LIBS ${ZSTD_LIBRARIES}) - list(APPEND CURL_LIBDIRS ${ZSTD_LIBRARY_DIRS}) - list(APPEND LIBCURL_PC_REQUIRES_PRIVATE ${ZSTD_PC_REQUIRES}) - include_directories(SYSTEM ${ZSTD_INCLUDE_DIRS}) - link_directories(${ZSTD_LIBRARY_DIRS}) - if(ZSTD_CFLAGS) - string(APPEND CMAKE_C_FLAGS " ${ZSTD_CFLAGS}") - endif() + list(APPEND CURL_LIBS CURL::zstd) else() message(WARNING "zstd v1.0.0 or newer is required, disabling zstd support.") endif() @@ -1023,21 +924,19 @@ macro(curl_openssl_check_exists) if(HAVE_LIBZ) list(APPEND CMAKE_REQUIRED_LIBRARIES ZLIB::ZLIB) endif() - if(WIN32 AND NOT WINCE) + if(WIN32) list(APPEND CMAKE_REQUIRED_LIBRARIES "bcrypt") # for OpenSSL/LibreSSL endif() endif() if(USE_WOLFSSL) - list(APPEND CMAKE_REQUIRED_INCLUDES "${WOLFSSL_INCLUDE_DIRS}") - list(APPEND CMAKE_REQUIRED_LIBRARIES "${WOLFSSL_LIBRARIES}") - curl_required_libpaths("${WOLFSSL_LIBRARY_DIRS}") + list(APPEND CMAKE_REQUIRED_LIBRARIES CURL::wolfssl) if(HAVE_LIBZ) list(APPEND CMAKE_REQUIRED_LIBRARIES ZLIB::ZLIB) # Public wolfSSL headers also require zlib headers endif() list(APPEND CMAKE_REQUIRED_DEFINITIONS "-DHAVE_UINTPTR_T") # to pull in stdint.h (as of wolfSSL v5.5.4) endif() if(WIN32) - list(APPEND CMAKE_REQUIRED_LIBRARIES "${_win32_winsock}" "${_win32_crypt32}") # for OpenSSL/wolfSSL + list(APPEND CMAKE_REQUIRED_LIBRARIES "ws2_32" "crypt32") # for OpenSSL/wolfSSL endif() if(${ARGC} EQUAL 2) check_function_exists(${ARGN}) @@ -1079,6 +978,9 @@ if(USE_WOLFSSL) endif() if(USE_OPENSSL) + if(NOT DEFINED HAVE_DES_ECB_ENCRYPT) + curl_openssl_check_exists("DES_ecb_encrypt" "openssl/des.h" HAVE_DES_ECB_ENCRYPT) + endif() if(NOT DEFINED HAVE_SSL_SET0_WBIO) curl_openssl_check_exists("SSL_set0_wbio" HAVE_SSL_SET0_WBIO) endif() @@ -1129,14 +1031,7 @@ option(USE_NGHTTP2 "Use nghttp2 library" ON) if(USE_NGHTTP2) find_package(NGHTTP2) if(NGHTTP2_FOUND) - list(APPEND CURL_LIBS ${NGHTTP2_LIBRARIES}) - list(APPEND CURL_LIBDIRS ${NGHTTP2_LIBRARY_DIRS}) - list(APPEND LIBCURL_PC_REQUIRES_PRIVATE ${NGHTTP2_PC_REQUIRES}) - include_directories(SYSTEM ${NGHTTP2_INCLUDE_DIRS}) - link_directories(${NGHTTP2_LIBRARY_DIRS}) - if(NGHTTP2_CFLAGS) - string(APPEND CMAKE_C_FLAGS " ${NGHTTP2_CFLAGS}") - endif() + list(APPEND CURL_LIBS CURL::nghttp2) else() set(USE_NGHTTP2 OFF) endif() @@ -1172,25 +1067,11 @@ if(USE_NGTCP2) else() message(FATAL_ERROR "ngtcp2 requires a supported TLS-backend") endif() - list(APPEND CURL_LIBS ${NGTCP2_LIBRARIES}) - list(APPEND CURL_LIBDIRS ${NGTCP2_LIBRARY_DIRS}) - list(APPEND LIBCURL_PC_REQUIRES_PRIVATE ${NGTCP2_PC_REQUIRES}) - include_directories(SYSTEM ${NGTCP2_INCLUDE_DIRS}) - link_directories(${NGTCP2_LIBRARY_DIRS}) - if(NGTCP2_CFLAGS) - string(APPEND CMAKE_C_FLAGS " ${NGTCP2_CFLAGS}") - endif() + list(APPEND CURL_LIBS CURL::ngtcp2) find_package(NGHTTP3 REQUIRED) set(USE_NGHTTP3 ON) - list(APPEND CURL_LIBS ${NGHTTP3_LIBRARIES}) - list(APPEND CURL_LIBDIRS ${NGHTTP3_LIBRARY_DIRS}) - list(APPEND LIBCURL_PC_REQUIRES_PRIVATE ${NGHTTP3_PC_REQUIRES}) - include_directories(SYSTEM ${NGHTTP3_INCLUDE_DIRS}) - link_directories(${NGHTTP3_LIBRARY_DIRS}) - if(NGHTTP3_CFLAGS) - string(APPEND CMAKE_C_FLAGS " ${NGHTTP3_CFLAGS}") - endif() + list(APPEND CURL_LIBS CURL::nghttp3) endif() option(USE_QUICHE "Use quiche library for HTTP/3 support" OFF) @@ -1205,18 +1086,10 @@ if(USE_QUICHE) message(FATAL_ERROR "quiche requires BoringSSL") endif() curl_openssl_check_quic() - list(APPEND CURL_LIBS ${QUICHE_LIBRARIES}) - list(APPEND CURL_LIBDIRS ${QUICHE_LIBRARY_DIRS}) - list(APPEND LIBCURL_PC_REQUIRES_PRIVATE ${QUICHE_PC_REQUIRES}) - include_directories(SYSTEM ${QUICHE_INCLUDE_DIRS}) - link_directories(${QUICHE_LIBRARY_DIRS}) - if(QUICHE_CFLAGS) - string(APPEND CMAKE_C_FLAGS " ${QUICHE_CFLAGS}") - endif() + list(APPEND CURL_LIBS CURL::quiche) if(NOT DEFINED HAVE_QUICHE_CONN_SET_QLOG_FD) cmake_push_check_state() - list(APPEND CMAKE_REQUIRED_INCLUDES "${QUICHE_INCLUDE_DIRS}") - list(APPEND CMAKE_REQUIRED_LIBRARIES "${QUICHE_LIBRARIES}") + list(APPEND CMAKE_REQUIRED_LIBRARIES CURL::quiche) check_symbol_exists("quiche_conn_set_qlog_fd" "quiche.h" HAVE_QUICHE_CONN_SET_QLOG_FD) cmake_pop_check_state() endif() @@ -1232,14 +1105,7 @@ if(USE_OPENSSL_QUIC) find_package(NGHTTP3 REQUIRED) set(USE_NGHTTP3 ON) - list(APPEND CURL_LIBS ${NGHTTP3_LIBRARIES}) - list(APPEND CURL_LIBDIRS ${NGHTTP3_LIBRARY_DIRS}) - list(APPEND LIBCURL_PC_REQUIRES_PRIVATE ${NGHTTP3_PC_REQUIRES}) - include_directories(SYSTEM ${NGHTTP3_INCLUDE_DIRS}) - link_directories(${NGHTTP3_LIBRARY_DIRS}) - if(NGHTTP3_CFLAGS) - string(APPEND CMAKE_C_FLAGS " ${NGHTTP3_CFLAGS}") - endif() + list(APPEND CURL_LIBS CURL::nghttp3) endif() if(NOT CURL_DISABLE_SRP AND (HAVE_GNUTLS_SRP OR HAVE_OPENSSL_SRP)) @@ -1247,7 +1113,7 @@ if(NOT CURL_DISABLE_SRP AND (HAVE_GNUTLS_SRP OR HAVE_OPENSSL_SRP)) endif() if(NOT CURL_DISABLE_LDAP) - if(WIN32 AND NOT WINDOWS_STORE AND NOT WINCE) + if(WIN32 AND NOT WINDOWS_STORE) option(USE_WIN32_LDAP "Use Windows LDAP implementation" ON) if(USE_WIN32_LDAP) list(APPEND CURL_LIBS "wldap32") @@ -1267,22 +1133,12 @@ if(NOT CURL_DISABLE_LDAP) find_package(LDAP) if(LDAP_FOUND) set(HAVE_LBER_H 1) - set(CURL_LIBS ${LDAP_LIBRARIES} ${CURL_LIBS}) - list(APPEND CURL_LIBDIRS ${LDAP_LIBRARY_DIRS}) - if(LDAP_PC_REQUIRES) - set(LIBCURL_PC_REQUIRES_PRIVATE ${LDAP_PC_REQUIRES} ${LIBCURL_PC_REQUIRES_PRIVATE}) - endif() - include_directories(SYSTEM ${LDAP_INCLUDE_DIRS}) - link_directories(${LDAP_LIBRARY_DIRS}) - if(LDAP_CFLAGS) - string(APPEND CMAKE_C_FLAGS " ${LDAP_CFLAGS}") - endif() + set(CURL_LIBS CURL::ldap ${CURL_LIBS}) # LDAP feature checks list(APPEND CMAKE_REQUIRED_DEFINITIONS "-DLDAP_DEPRECATED=1") - list(APPEND CMAKE_REQUIRED_LIBRARIES "${LDAP_LIBRARIES}") - curl_required_libpaths("${LDAP_LIBRARY_DIRS}") + list(APPEND CMAKE_REQUIRED_LIBRARIES CURL::ldap) check_function_exists("ldap_url_parse" HAVE_LDAP_URL_PARSE) check_function_exists("ldap_init_fd" HAVE_LDAP_INIT_FD) @@ -1344,14 +1200,7 @@ set(HAVE_LIBIDN2 OFF) if(USE_LIBIDN2 AND NOT USE_APPLE_IDN AND NOT USE_WIN32_IDN) find_package(Libidn2) if(LIBIDN2_FOUND) - set(CURL_LIBS ${LIBIDN2_LIBRARIES} ${CURL_LIBS}) - list(APPEND CURL_LIBDIRS ${LIBIDN2_LIBRARY_DIRS}) - set(LIBCURL_PC_REQUIRES_PRIVATE ${LIBIDN2_PC_REQUIRES} ${LIBCURL_PC_REQUIRES_PRIVATE}) - include_directories(SYSTEM ${LIBIDN2_INCLUDE_DIRS}) - link_directories(${LIBIDN2_LIBRARY_DIRS}) - if(LIBIDN2_CFLAGS) - string(APPEND CMAKE_C_FLAGS " ${LIBIDN2_CFLAGS}") - endif() + set(CURL_LIBS CURL::libidn2 ${CURL_LIBS}) set(HAVE_IDN2_H 1) set(HAVE_LIBIDN2 1) endif() @@ -1361,17 +1210,9 @@ endif() option(CURL_USE_LIBPSL "Use libpsl" ON) mark_as_advanced(CURL_USE_LIBPSL) set(USE_LIBPSL OFF) - if(CURL_USE_LIBPSL) find_package(Libpsl REQUIRED) - list(APPEND CURL_LIBS ${LIBPSL_LIBRARIES}) - list(APPEND CURL_LIBDIRS ${LIBPSL_LIBRARY_DIRS}) - list(APPEND LIBCURL_PC_REQUIRES_PRIVATE ${LIBPSL_PC_REQUIRES}) - include_directories(SYSTEM ${LIBPSL_INCLUDE_DIRS}) - link_directories(${LIBPSL_LIBRARY_DIRS}) - if(LIBPSL_CFLAGS) - string(APPEND CMAKE_C_FLAGS " ${LIBPSL_CFLAGS}") - endif() + list(APPEND CURL_LIBS CURL::libpsl) set(USE_LIBPSL ON) endif() @@ -1379,18 +1220,10 @@ endif() option(CURL_USE_LIBSSH2 "Use libssh2" ON) mark_as_advanced(CURL_USE_LIBSSH2) set(USE_LIBSSH2 OFF) - if(CURL_USE_LIBSSH2) find_package(Libssh2) if(LIBSSH2_FOUND) - set(CURL_LIBS ${LIBSSH2_LIBRARIES} ${CURL_LIBS}) # keep it before TLS-crypto, compression - list(APPEND CURL_LIBDIRS ${LIBSSH2_LIBRARY_DIRS}) - set(LIBCURL_PC_REQUIRES_PRIVATE ${LIBSSH2_PC_REQUIRES} ${LIBCURL_PC_REQUIRES_PRIVATE}) - include_directories(SYSTEM ${LIBSSH2_INCLUDE_DIRS}) - link_directories(${LIBSSH2_LIBRARY_DIRS}) - if(LIBSSH2_CFLAGS) - string(APPEND CMAKE_C_FLAGS " ${LIBSSH2_CFLAGS}") - endif() + set(CURL_LIBS CURL::libssh2 ${CURL_LIBS}) # keep it before TLS-crypto, compression set(USE_LIBSSH2 ON) endif() endif() @@ -1400,14 +1233,7 @@ option(CURL_USE_LIBSSH "Use libssh" OFF) mark_as_advanced(CURL_USE_LIBSSH) if(NOT USE_LIBSSH2 AND CURL_USE_LIBSSH) find_package(Libssh REQUIRED) - set(CURL_LIBS ${LIBSSH_LIBRARIES} ${CURL_LIBS}) # keep it before TLS-crypto, compression - list(APPEND CURL_LIBDIRS ${LIBSSH_LIBRARY_DIRS}) - set(LIBCURL_PC_REQUIRES_PRIVATE ${LIBSSH_PC_REQUIRES} ${LIBCURL_PC_REQUIRES_PRIVATE}) - include_directories(SYSTEM ${LIBSSH_INCLUDE_DIRS}) - link_directories(${LIBSSH_LIBRARY_DIRS}) - if(LIBSSH_CFLAGS) - string(APPEND CMAKE_C_FLAGS " ${LIBSSH_CFLAGS}") - endif() + set(CURL_LIBS CURL::libssh ${CURL_LIBS}) # keep it before TLS-crypto, compression set(USE_LIBSSH ON) endif() @@ -1415,14 +1241,7 @@ option(CURL_USE_GSASL "Use libgsasl" OFF) mark_as_advanced(CURL_USE_GSASL) if(CURL_USE_GSASL) find_package(Libgsasl REQUIRED) - list(APPEND CURL_LIBS ${LIBGSASL_LIBRARIES}) - list(APPEND CURL_LIBDIRS ${LIBGSASL_LIBRARY_DIRS}) - list(APPEND LIBCURL_PC_REQUIRES_PRIVATE ${LIBGSASL_PC_REQUIRES}) - include_directories(SYSTEM ${LIBGSASL_INCLUDE_DIRS}) - link_directories(${LIBGSASL_LIBRARY_DIRS}) - if(LIBGSASL_CFLAGS) - string(APPEND CMAKE_C_FLAGS " ${LIBGSASL_CFLAGS}") - endif() + list(APPEND CURL_LIBS CURL::libgsasl) set(USE_GSASL ON) endif() @@ -1434,16 +1253,10 @@ if(CURL_USE_GSSAPI) set(HAVE_GSSAPI ${GSS_FOUND}) if(GSS_FOUND) - list(APPEND CURL_LIBS ${GSS_LIBRARIES}) - list(APPEND CURL_LIBDIRS ${GSS_LIBRARY_DIRS}) - list(APPEND LIBCURL_PC_REQUIRES_PRIVATE ${GSS_PC_REQUIRES}) - include_directories(SYSTEM ${GSS_INCLUDE_DIRS}) - link_directories(${GSS_LIBRARY_DIRS}) - if(GSS_CFLAGS) - string(APPEND CMAKE_C_FLAGS " ${GSS_CFLAGS}") - endif() + list(APPEND CURL_LIBS CURL::gss) - if(GSS_FLAVOUR STREQUAL "GNU") + get_target_property(_gss_flavour CURL::gss INTERFACE_CURL_GSS_FLAVOUR) + if(_gss_flavour STREQUAL "GNU") set(HAVE_GSSGNU 1) elseif(GSS_VERSION) # MIT set(CURL_KRB5_VERSION "\"${GSS_VERSION}\"") @@ -1453,6 +1266,20 @@ if(CURL_USE_GSSAPI) endif() endif() +# libbacktrace +option(CURL_USE_LIBBACKTRACE "Use libbacktrace. Requires build with TrackMemory and DWARF debug information." OFF) +if(CURL_USE_LIBBACKTRACE) + if(NOT ENABLE_CURLDEBUG) + message(FATAL_ERROR "libbacktrace requires TrackMemory enabled") + endif() + if(NOT CMAKE_BUILD_TYPE MATCHES "(Debug|RelWithDebInfo)") + message(FATAL_ERROR "libbacktrace requires debug information") + endif() + find_package(Libbacktrace REQUIRED) + list(APPEND CURL_LIBS CURL::libbacktrace) + set(USE_BACKTRACE ON) +endif() + # libuv option(CURL_USE_LIBUV "Use libuv for event-based tests" OFF) if(CURL_USE_LIBUV) @@ -1460,14 +1287,7 @@ if(CURL_USE_LIBUV) message(FATAL_ERROR "Using libuv without debug support enabled is useless") endif() find_package(Libuv REQUIRED) - list(APPEND CURL_LIBS ${LIBUV_LIBRARIES}) - list(APPEND CURL_LIBDIRS ${LIBUV_LIBRARY_DIRS}) - list(APPEND LIBCURL_PC_REQUIRES_PRIVATE ${LIBUV_PC_REQUIRES}) - include_directories(SYSTEM ${LIBUV_INCLUDE_DIRS}) - link_directories(${LIBUV_LIBRARY_DIRS}) - if(LIBUV_CFLAGS) - string(APPEND CMAKE_C_FLAGS " ${LIBUV_CFLAGS}") - endif() + list(APPEND CURL_LIBS CURL::libuv) set(USE_LIBUV ON) set(HAVE_UV_H ON) endif() @@ -1475,18 +1295,11 @@ endif() option(USE_LIBRTMP "Enable librtmp from rtmpdump" OFF) if(USE_LIBRTMP) find_package(Librtmp REQUIRED) - list(APPEND CURL_LIBS ${LIBRTMP_LIBRARIES}) - list(APPEND CURL_LIBDIRS ${LIBRTMP_LIBRARY_DIRS}) - list(APPEND LIBCURL_PC_REQUIRES_PRIVATE ${LIBRTMP_PC_REQUIRES}) - include_directories(SYSTEM ${LIBRTMP_INCLUDE_DIRS}) - link_directories(${LIBRTMP_LIBRARY_DIRS}) - if(LIBRTMP_CFLAGS) - string(APPEND CMAKE_C_FLAGS " ${LIBRTMP_CFLAGS}") - endif() + list(APPEND CURL_LIBS CURL::librtmp) endif() option(ENABLE_UNIX_SOCKETS "Enable Unix domain sockets support" ON) -if(ENABLE_UNIX_SOCKETS AND NOT WINCE) +if(ENABLE_UNIX_SOCKETS) if(WIN32 OR DOS) set(USE_UNIX_SOCKETS 1) else() @@ -1502,14 +1315,16 @@ endif() # CA handling # if(_curl_ca_bundle_supported) + set(_ca_opt_desc "Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.") + set(CURL_CA_BUNDLE "auto" CACHE - STRING "Path to the CA bundle. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.") + STRING "Absolute path to the CA bundle. ${_ca_opt_desc}") set(CURL_CA_FALLBACK OFF CACHE BOOL "Use built-in CA store of OpenSSL. Defaults to OFF") set(CURL_CA_PATH "auto" CACHE - STRING "Location of default CA path. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.") + STRING "Absolute path to a directory containing CA certificates stored individually. ${_ca_opt_desc}") set(CURL_CA_EMBED "" CACHE - STRING "Path to the CA bundle to embed in the curl tool.") + STRING "Absolute path to the CA bundle to embed in the curl tool.") if(CURL_CA_FALLBACK AND NOT CURL_USE_OPENSSL) message(FATAL_ERROR "CURL_CA_FALLBACK only works with OpenSSL.") @@ -1535,7 +1350,7 @@ if(_curl_ca_bundle_supported) unset(CURL_CA_PATH CACHE) elseif(CURL_CA_PATH STREQUAL "auto") unset(CURL_CA_PATH CACHE) - if(NOT CMAKE_CROSSCOMPILING AND NOT WIN32) + if(NOT CMAKE_CROSSCOMPILING AND NOT WIN32 AND NOT USE_APPLE_SECTRUST) set(_curl_ca_path_autodetect TRUE) endif() else() @@ -1560,8 +1375,8 @@ if(_curl_ca_bundle_supported) if(EXISTS "${_search_ca_bundle_path}") message(STATUS "Found CA bundle: ${_search_ca_bundle_path}") set(CURL_CA_BUNDLE "${_search_ca_bundle_path}" CACHE - STRING "Path to the CA bundle. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.") - set(CURL_CA_BUNDLE_SET TRUE CACHE BOOL "Path to the CA bundle has been set") + STRING "Absolute path to the CA bundle. ${_ca_opt_desc}") + set(CURL_CA_BUNDLE_SET TRUE CACHE BOOL "Absolute path to the CA bundle has been set") break() endif() endforeach() @@ -1574,8 +1389,8 @@ if(_curl_ca_bundle_supported) unset(_curl_ca_files_found) message(STATUS "Found CA path: ${_search_ca_path}") set(CURL_CA_PATH "${_search_ca_path}" CACHE - STRING "Location of default CA path. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.") - set(CURL_CA_PATH_SET TRUE CACHE BOOL "Path to the CA bundle has been set") + STRING "Absolute path to a directory containing CA certificates stored individually. ${_ca_opt_desc}") + set(CURL_CA_PATH_SET TRUE CACHE BOOL "Absolute path to the CA bundle has been set") endif() endif() endif() @@ -1601,7 +1416,7 @@ if(WIN32) list(APPEND CURL_INCLUDES "winsock2.h") list(APPEND CURL_INCLUDES "ws2tcpip.h") - if(HAVE_WIN32_WINNT AND HAVE_WIN32_WINNT LESS 0x0501 AND NOT WINCE) + if(HAVE_WIN32_WINNT AND HAVE_WIN32_WINNT LESS 0x0501) # Windows XP is required for freeaddrinfo, getaddrinfo message(FATAL_ERROR "Building for Windows XP or newer is required.") endif() @@ -1609,7 +1424,7 @@ if(WIN32) # Pre-fill detection results based on target OS version if(_CURL_PREFILL) if(NOT HAVE_WIN32_WINNT OR HAVE_WIN32_WINNT LESS 0x0600 OR # older than Windows Vista - WINCE OR WINDOWS_STORE) + WINDOWS_STORE) set(HAVE_IF_NAMETOINDEX 0) unset(HAVE_IF_NAMETOINDEX CACHE) elseif(MSVC OR MINGW) @@ -1717,8 +1532,8 @@ endif() # Apply to all feature checks if(WIN32) - list(APPEND CMAKE_REQUIRED_LIBRARIES "${_win32_winsock}") - if(NOT WINCE AND NOT WINDOWS_STORE) + list(APPEND CMAKE_REQUIRED_LIBRARIES "ws2_32") + if(NOT WINDOWS_STORE) list(APPEND CMAKE_REQUIRED_LIBRARIES "iphlpapi") endif() elseif(HAVE_LIBSOCKET) @@ -1755,6 +1570,7 @@ check_function_exists("getpwuid_r" HAVE_GETPWUID_R) check_function_exists("geteuid" HAVE_GETEUID) check_function_exists("utime" HAVE_UTIME) check_symbol_exists("gmtime_r" "stdlib.h;time.h" HAVE_GMTIME_R) +check_symbol_exists("localtime_r" "stdlib.h;time.h" HAVE_LOCALTIME_R) check_symbol_exists("gethostbyname_r" "netdb.h" HAVE_GETHOSTBYNAME_R) check_symbol_exists("gethostname" "${CURL_INCLUDES}" HAVE_GETHOSTNAME) # winsock2.h unistd.h proto/bsdsocket.h @@ -1772,9 +1588,9 @@ check_function_exists("eventfd" HAVE_EVENTFD) check_symbol_exists("ftruncate" "unistd.h" HAVE_FTRUNCATE) check_symbol_exists("getpeername" "${CURL_INCLUDES}" HAVE_GETPEERNAME) # winsock2.h unistd.h proto/bsdsocket.h check_symbol_exists("getsockname" "${CURL_INCLUDES}" HAVE_GETSOCKNAME) # winsock2.h unistd.h proto/bsdsocket.h -check_function_exists("getrlimit" HAVE_GETRLIMIT) -check_function_exists("setlocale" HAVE_SETLOCALE) -check_function_exists("setrlimit" HAVE_SETRLIMIT) +check_function_exists("getrlimit" HAVE_GETRLIMIT) +check_function_exists("setlocale" HAVE_SETLOCALE) +check_function_exists("setrlimit" HAVE_SETRLIMIT) if(WIN32) # include wincrypt.h as a workaround for mingw-w64 __MINGW64_VERSION_MAJOR <= 5 header bug */ @@ -1783,16 +1599,14 @@ else() check_function_exists("if_nametoindex" HAVE_IF_NAMETOINDEX) # net/if.h check_function_exists("realpath" HAVE_REALPATH) check_function_exists("sched_yield" HAVE_SCHED_YIELD) - check_symbol_exists("strcasecmp" "string.h" HAVE_STRCASECMP) - check_symbol_exists("stricmp" "string.h" HAVE_STRICMP) - check_symbol_exists("strcmpi" "string.h" HAVE_STRCMPI) + check_symbol_exists("strcasecmp" "string.h" HAVE_STRCASECMP) + check_symbol_exists("stricmp" "string.h" HAVE_STRICMP) + check_symbol_exists("strcmpi" "string.h" HAVE_STRCMPI) endif() -if(NOT MINGW32CE) # Avoid false detections - check_function_exists("setmode" HAVE_SETMODE) - if(WIN32 OR CYGWIN) - check_function_exists("_setmode" HAVE__SETMODE) - endif() +check_function_exists("setmode" HAVE_SETMODE) +if(WIN32 OR CYGWIN) + check_function_exists("_setmode" HAVE__SETMODE) endif() if(AMIGA) @@ -1890,7 +1704,7 @@ check_type_size("off_t" SIZEOF_OFF_T) if(NOT WIN32) # fseeko may not exist with _FILE_OFFSET_BITS=64 but can exist with - # _FILE_OFFSET_BITS unset or 32 (e.g. Android ARMv7 with NDK 26b and API level < 24) + # _FILE_OFFSET_BITS unset or 32 (as in Android ARMv7 with NDK 26b and API level < 24) # so we need to test fseeko after testing for _FILE_OFFSET_BITS check_symbol_exists("fseeko" "${CURL_INCLUDES};stdio.h" HAVE_FSEEKO) @@ -1954,17 +1768,11 @@ include(CMake/OtherTests.cmake) set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS "HAVE_CONFIG_H") if(WIN32) - list(APPEND CURL_NETWORK_AND_TIME_LIBS "${_win32_winsock}") - if(NOT WINCE AND NOT WINDOWS_STORE) + list(APPEND CURL_NETWORK_AND_TIME_LIBS "ws2_32") + if(NOT WINDOWS_STORE) list(APPEND CURL_NETWORK_AND_TIME_LIBS "iphlpapi") endif() - if(NOT WINCE) - list(APPEND CURL_LIBS "bcrypt") - endif() - - if(NOT WINCE) - set(USE_WIN32_LARGE_FILES ON) - endif() + list(APPEND CURL_LIBS "bcrypt") # We use crypto functions that are not available for UWP apps if(NOT WINDOWS_STORE) @@ -1973,13 +1781,10 @@ if(WIN32) # Link required libraries for USE_WIN32_CRYPTO or USE_SCHANNEL if(USE_WIN32_CRYPTO OR USE_SCHANNEL) - if(NOT WINCE) - list(APPEND CURL_LIBS "advapi32") - endif() - list(APPEND CURL_LIBS "${_win32_crypt32}") + list(APPEND CURL_LIBS "advapi32" "crypt32") endif() if(USE_WINDOWS_SSPI) - list(APPEND CURL_LIBS "${_win32_secur32}") + list(APPEND CURL_LIBS "secur32") endif() endif() @@ -1988,6 +1793,28 @@ if(CURL_CODE_COVERAGE) list(APPEND CURL_LIBS ${CURL_COVERAGE_LIBS}) endif() +# Hack to add some libraries to the end of the library list to make binutils ld +# for GCC find symbols when linking statically. Necessary for libs detected via +# CMake's built-in find modules, which CMake adds to the beginning of the lib +# list on the linker command-line for some reason. This makes them appear +# before dependencies detected via curl's custom Find modules, and breaks +# linkers sensitive to lib order. There must be a better solution to this. +if(CMAKE_C_COMPILER_ID STREQUAL "GNU") + foreach(_lib IN ITEMS OpenSSL::Crypto ZLIB::ZLIB) + if(TARGET "${_lib}") + add_library(CURL::${_lib} INTERFACE IMPORTED) + get_target_property(_libname "${_lib}" LOCATION) + set_target_properties(${_lib} PROPERTIES INTERFACE_LINK_LIBRARIES "${_libname}") + list(APPEND CURL_LIBS ${_lib}) + endif() + endforeach() + if(WIN32) + add_library(CURL::win32_winsock INTERFACE IMPORTED) + set_target_properties(CURL::win32_winsock PROPERTIES INTERFACE_LINK_LIBRARIES "ws2_32") + list(APPEND CURL_LIBS CURL::win32_winsock) + endif() +endif() + if(CMAKE_C_COMPILER_ID STREQUAL "MSVC") # MSVC but exclude clang-cl set_property(DIRECTORY APPEND PROPERTY COMPILE_OPTIONS "-MP") # Parallel compilation endif() @@ -2008,14 +1835,12 @@ if(CURL_LTO) endif() endif() - # Ugly (but functional) way to include "Makefile.inc" by transforming it # (= regenerate it). function(curl_transform_makefile_inc _input_file _output_file) file(READ ${_input_file} _makefile_inc_text) - # cmake-lint: disable=W0106 - string(REPLACE "$(top_srcdir)" "\${PROJECT_SOURCE_DIR}" _makefile_inc_text ${_makefile_inc_text}) - string(REPLACE "$(top_builddir)" "\${PROJECT_BINARY_DIR}" _makefile_inc_text ${_makefile_inc_text}) + string(REPLACE "$(top_srcdir)" "\${PROJECT_SOURCE_DIR}" _makefile_inc_text ${_makefile_inc_text}) # cmake-lint: disable=W0106 + string(REPLACE "$(top_builddir)" "\${PROJECT_BINARY_DIR}" _makefile_inc_text ${_makefile_inc_text}) # cmake-lint: disable=W0106 string(REGEX REPLACE "\\\\\n" "!^!^!" _makefile_inc_text ${_makefile_inc_text}) string(REGEX REPLACE "([a-zA-Z_][a-zA-Z0-9_]*)[\t ]*=[\t ]*([^\n]*)" "set(\\1 \\2)" _makefile_inc_text ${_makefile_inc_text}) @@ -2039,13 +1864,13 @@ set(_project_config "${_generated_dir}/${PROJECT_NAME}Config.cmake") set(_version_config "${_generated_dir}/${PROJECT_NAME}ConfigVersion.cmake") option(BUILD_TESTING "Build tests" ON) -if(BUILD_TESTING AND PERL_FOUND) +if(BUILD_TESTING AND Perl_FOUND) set(CURL_BUILD_TESTING ON) else() set(CURL_BUILD_TESTING OFF) endif() -if(PERL_FOUND) +if(Perl_FOUND) set(CURL_MANPAGE "${PROJECT_BINARY_DIR}/docs/cmdline-opts/curl.1") set(CURL_ASCIIPAGE "${PROJECT_BINARY_DIR}/docs/cmdline-opts/curl.txt") add_subdirectory(docs) @@ -2053,8 +1878,6 @@ endif() add_subdirectory(scripts) # for shell completions -list(REMOVE_DUPLICATES CURL_LIBDIRS) - add_subdirectory(lib) if(BUILD_CURL_EXE) @@ -2082,8 +1905,8 @@ endmacro() # NTLM support requires crypto functions from various SSL libs. # These conditions must match those in lib/curl_setup.h. if(NOT CURL_DISABLE_NTLM AND - (USE_OPENSSL OR - USE_MBEDTLS OR + ((USE_OPENSSL AND HAVE_DES_ECB_ENCRYPT) OR + (USE_MBEDTLS AND HAVE_MBEDTLS_DES_CRYPT_ECB) OR USE_GNUTLS OR USE_WIN32_CRYPTO OR (USE_WOLFSSL AND HAVE_WOLFSSL_DES_ECB_ENCRYPT))) @@ -2148,8 +1971,7 @@ curl_add_if("asyn-rr" USE_ARES AND ENABLE_THREADED_RESOLVER AND USE_HTTPSR curl_add_if("IDN" (HAVE_LIBIDN2 AND HAVE_IDN2_H) OR USE_WIN32_IDN OR USE_APPLE_IDN) -curl_add_if("Largefile" (SIZEOF_CURL_OFF_T GREATER 4) AND - ((SIZEOF_OFF_T GREATER 4) OR USE_WIN32_LARGE_FILES)) +curl_add_if("Largefile" (SIZEOF_CURL_OFF_T GREATER 4) AND ((SIZEOF_OFF_T GREATER 4) OR WIN32)) curl_add_if("SSPI" USE_WINDOWS_SSPI) curl_add_if("GSS-API" HAVE_GSSAPI) curl_add_if("alt-svc" NOT CURL_DISABLE_ALTSVC) @@ -2193,8 +2015,7 @@ message(STATUS "Features: ${SUPPORT_FEATURES}") # Clear list and collect SSL backends set(_items "") curl_add_if("Schannel" _ssl_enabled AND USE_SCHANNEL) -curl_add_if("${_openssl}" _ssl_enabled AND USE_OPENSSL AND OPENSSL_VERSION VERSION_LESS 3.0.0) -curl_add_if("${_openssl} v3+" _ssl_enabled AND USE_OPENSSL AND OPENSSL_VERSION VERSION_GREATER_EQUAL 3.0.0) +curl_add_if("${_openssl}" _ssl_enabled AND USE_OPENSSL) curl_add_if("mbedTLS" _ssl_enabled AND USE_MBEDTLS) curl_add_if("wolfSSL" _ssl_enabled AND USE_WOLFSSL) curl_add_if("GnuTLS" _ssl_enabled AND USE_GNUTLS) @@ -2278,67 +2099,104 @@ if(NOT CURL_DISABLE_INSTALL) endif() endforeach() - foreach(_libdir IN LISTS _custom_libdirs CURL_LIBDIRS) - if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.20) - cmake_path(SET _libdir NORMALIZE "${_libdir}") - endif() - list(FIND _sys_libdirs "${_libdir}" _libdir_index) - if(_libdir_index LESS 0) - list(APPEND _ldflags "-L${_libdir}") - endif() - endforeach() - set(_implicit_libs "") if(NOT MINGW AND NOT UNIX) set(_implicit_libs "${CMAKE_C_IMPLICIT_LINK_LIBRARIES}") endif() - foreach(_lib IN LISTS _implicit_libs _custom_libs CURL_LIBS) + set(_explicit_libdirs "") + set(LIBCURL_PC_REQUIRES_PRIVATE "") + set(LIBCURL_PC_LIBS_PRIVATE_LIST "") + foreach(_lib IN LISTS CURL_LIBS _custom_libs _implicit_libs) if(TARGET "${_lib}") - set(_libname "${_lib}") - get_target_property(_imported "${_libname}" IMPORTED) + set(_explicit_libs "") + get_target_property(_imported "${_lib}" IMPORTED) if(NOT _imported) # Reading the LOCATION property on non-imported target will error out. # Assume the user will not need this information in the .pc file. continue() endif() - get_target_property(_lib "${_libname}" LOCATION) - if(NOT _lib) - message(WARNING "Bad lib in library list: ${_libname}") - continue() - endif() - endif() - if(_lib MATCHES "^-") # '-framework ' - list(APPEND _ldflags "${_lib}") - elseif(_lib MATCHES "/") - # This gets a bit more complex, because we want to specify the - # directory separately, and only once per directory - if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.20) - cmake_path(GET _lib PARENT_PATH _libdir) - cmake_path(GET _lib STEM _libname) + if(_lib MATCHES "CURL::") + # This is empty for 'CURL::*' targets and safe to ignore. + # Explicitly skip this query to avoid CMake v3.18 and older erroring out. + set(_libname "") else() - get_filename_component(_libdir "${_lib}" DIRECTORY) - get_filename_component(_libname "${_lib}" NAME_WE) + get_target_property(_libname "${_lib}" LOCATION) endif() - if(_libname MATCHES "^lib") - if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.20) - cmake_path(SET _libdir NORMALIZE "${_libdir}") + if(_libname) + list(APPEND _explicit_libs "${_libname}") + else() + get_target_property(_libs "${_lib}" INTERFACE_LINK_LIBRARIES) + if(_libs) + list(APPEND _explicit_libs "${_libs}") endif() - list(FIND _sys_libdirs "${_libdir}" _libdir_index) - if(_libdir_index LESS 0) - list(APPEND _ldflags "-L${_libdir}") + get_target_property(_libdirs "${_lib}" INTERFACE_LINK_DIRECTORIES) + if(_libdirs) + list(APPEND _explicit_libdirs "${_libdirs}") endif() - string(REGEX REPLACE "^lib" "" _libname "${_libname}") - list(APPEND LIBCURL_PC_LIBS_PRIVATE "-l${_libname}") - else() - list(APPEND LIBCURL_PC_LIBS_PRIVATE "${_lib}") endif() + if(NOT _libname AND NOT _libs AND NOT _libdirs) + message(WARNING "Bad lib in library list: ${_lib}") + endif() + get_target_property(_modules "${_lib}" INTERFACE_LIBCURL_PC_MODULES) + if(_modules) + list(APPEND LIBCURL_PC_REQUIRES_PRIVATE "${_modules}") + endif() + + foreach(_lib IN LISTS _explicit_libs) + if(_lib MATCHES "/") + # This gets a bit more complex, because we want to specify the + # directory separately, and only once per directory + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.20) + cmake_path(GET _lib PARENT_PATH _libdir) + cmake_path(GET _lib STEM _libname) + else() + get_filename_component(_libdir "${_lib}" DIRECTORY) + get_filename_component(_libname "${_lib}" NAME_WE) + endif() + if(_libname MATCHES "^lib") + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.20) + cmake_path(SET _libdir NORMALIZE "${_libdir}") + endif() + list(FIND _sys_libdirs "${_libdir}" _libdir_index) + if(_libdir_index LESS 0) + list(APPEND _ldflags "-L${_libdir}") + endif() + string(REGEX REPLACE "^lib" "" _libname "${_libname}") + list(APPEND LIBCURL_PC_LIBS_PRIVATE "-l${_libname}") + list(APPEND LIBCURL_PC_LIBS_PRIVATE_LIST "${_lib}") + else() + list(APPEND LIBCURL_PC_LIBS_PRIVATE "${_lib}") + list(APPEND LIBCURL_PC_LIBS_PRIVATE_LIST "${_lib}") + endif() + else() + list(APPEND LIBCURL_PC_LIBS_PRIVATE "-l${_lib}") + list(APPEND LIBCURL_PC_LIBS_PRIVATE_LIST "${_lib}") + endif() + endforeach() + elseif(_lib MATCHES "^-") # '-framework ' + list(APPEND _ldflags "${_lib}") + list(APPEND LIBCURL_PC_LIBS_PRIVATE_LIST "${_lib}") else() list(APPEND LIBCURL_PC_LIBS_PRIVATE "-l${_lib}") + list(APPEND LIBCURL_PC_LIBS_PRIVATE_LIST "${_lib}") endif() endforeach() + foreach(_libdir IN LISTS _custom_libdirs _explicit_libdirs) + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.20) + cmake_path(SET _libdir NORMALIZE "${_libdir}") + endif() + list(FIND _sys_libdirs "${_libdir}" _libdir_index) + if(_libdir_index LESS 0) + list(APPEND _ldflags "-L${_libdir}") + endif() + endforeach() + + list(REMOVE_DUPLICATES _ldflags) + if(LIBCURL_PC_REQUIRES_PRIVATE) + list(REMOVE_DUPLICATES LIBCURL_PC_REQUIRES_PRIVATE) string(REPLACE ";" "," LIBCURL_PC_REQUIRES_PRIVATE "${LIBCURL_PC_REQUIRES_PRIVATE}") endif() if(LIBCURL_PC_LIBS_PRIVATE) @@ -2449,15 +2307,39 @@ if(NOT CURL_DISABLE_INSTALL) ${_generated_version_config}") # Consumed custom variables: + # CMAKE_MINIMUM_REQUIRED_VERSION # CURLVERSION + # LIBCURL_PC_LIBS_PRIVATE_LIST # LIB_NAME # LIB_SELECTED + # LIB_STATIC # TARGETS_EXPORT_NAME - # USE_OPENSSL OPENSSL_VERSION_MAJOR - # HAVE_LIBZ ZLIB_VERSION_MAJOR # CURL_SUPPORTED_FEATURES_LIST # CURL_SUPPORTED_PROTOCOLS_LIST - configure_package_config_file("CMake/curl-config.cmake.in" + # HAVE_BROTLI + # HAVE_GSSAPI + # HAVE_LIBIDN2 + # HAVE_LIBZ ZLIB_VERSION_MAJOR + # HAVE_ZSTD + # USE_ARES + # USE_BACKTRACE + # USE_GNUTLS + # USE_GSASL + # USE_LIBPSL + # USE_LIBRTMP + # USE_LIBSSH + # USE_LIBSSH2 + # USE_LIBUV + # USE_MBEDTLS + # USE_NGHTTP2 + # USE_NGHTTP3 + # USE_NGTCP2 + # USE_OPENSSL OPENSSL_VERSION_MAJOR + # USE_QUICHE + # USE_RUSTLS + # USE_WIN32_LDAP CURL_DISABLE_LDAP + # USE_WOLFSSL + configure_package_config_file("CMake/curl-config.in.cmake" "${_project_config}" INSTALL_DESTINATION ${_install_cmake_dir} PATH_VARS CMAKE_INSTALL_INCLUDEDIR) @@ -2468,12 +2350,37 @@ if(NOT CURL_DISABLE_INSTALL) DESTINATION ${_install_cmake_dir}) endif() - install(FILES ${_version_config} ${_project_config} + install( + FILES + ${_version_config} + ${_project_config} + "${CMAKE_CURRENT_SOURCE_DIR}/CMake/FindBrotli.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/CMake/FindCares.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/CMake/FindGSS.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/CMake/FindGnuTLS.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/CMake/FindLDAP.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/CMake/FindLibbacktrace.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/CMake/FindLibgsasl.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/CMake/FindLibidn2.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/CMake/FindLibpsl.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/CMake/FindLibrtmp.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/CMake/FindLibssh.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/CMake/FindLibssh2.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/CMake/FindLibuv.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/CMake/FindMbedTLS.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/CMake/FindNGHTTP2.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/CMake/FindNGHTTP3.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/CMake/FindNGTCP2.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/CMake/FindNettle.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/CMake/FindQuiche.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/CMake/FindRustls.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/CMake/FindWolfSSL.cmake" + "${CMAKE_CURRENT_SOURCE_DIR}/CMake/FindZstd.cmake" DESTINATION ${_install_cmake_dir}) if(NOT TARGET curl_uninstall) configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/CMake/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_SOURCE_DIR}/CMake/cmake_uninstall.in.cmake" "${CMAKE_CURRENT_BINARY_DIR}/CMake/cmake_uninstall.cmake" @ONLY) diff --git a/Dockerfile b/Dockerfile index 88a356bb88c5..e5f2b4073af0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -24,7 +24,7 @@ # $ ./scripts/maketgz 8.7.1 # To update, get the latest digest e.g. from https://hub.docker.com/_/debian/tags -FROM debian:bookworm-slim@sha256:7e490910eea2861b9664577a96b54ce68ea3e02ce7f51d89cb0103a6f9c386e0 +FROM debian:bookworm-slim@sha256:e899040a73d36e2b36fa33216943539d9957cba8172b858097c2cabcdb20a3e2 RUN apt-get update -qq && apt-get install -qq -y --no-install-recommends \ build-essential make autoconf automake libtool git perl zip zlib1g-dev gawk && \ diff --git a/GIT-INFO.md b/GIT-INFO.md index 1ff22010cbda..ee912560fd5a 100644 --- a/GIT-INFO.md +++ b/GIT-INFO.md @@ -1,3 +1,8 @@ + _ _ ____ _ ___| | | | _ \| | / __| | | | |_) | | diff --git a/Makefile.am b/Makefile.am index 76873854160c..5f6bb670e51c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -27,15 +27,16 @@ AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 CMAKE_DIST = \ - CMake/cmake_uninstall.cmake.in \ - CMake/CMakeConfigurableFile.in \ - CMake/curl-config.cmake.in \ + CMake/cmake_uninstall.in.cmake \ + CMake/curl-config.in.cmake \ CMake/CurlSymbolHiding.cmake \ CMake/CurlTests.c \ CMake/FindBrotli.cmake \ CMake/FindCares.cmake \ + CMake/FindGnuTLS.cmake \ CMake/FindGSS.cmake \ CMake/FindLDAP.cmake \ + CMake/FindLibbacktrace.cmake \ CMake/FindLibgsasl.cmake \ CMake/FindLibidn2.cmake \ CMake/FindLibpsl.cmake \ @@ -90,7 +91,7 @@ pkgconfig_DATA = libcurl.pc dist-hook: rm -rf $(top_builddir)/tests/log - find $(distdir) -name "*.dist" -exec rm {} \; + find $(distdir) -name "*.dist" -exec rm -- {} \; (distit=`find $(srcdir) -name "*.dist" | grep -v Makefile`; \ for file in $$distit; do \ strip=`echo $$file | sed -e s/^$(srcdir)// -e s/\.dist//`; \ @@ -110,7 +111,7 @@ pytest: test pytest-ci: test test: - @echo "NOTICE: we can't run the tests when cross-compiling!" + @echo "NOTICE: we cannot run the tests when cross-compiling!" else diff --git a/README b/README index df320f94810e..9401434b484e 100644 --- a/README +++ b/README @@ -15,7 +15,8 @@ README available to be used by your software. Read the libcurl.3 man page to learn how. - You find answers to the most frequent questions we get in the FAQ document. + You find answers to the most frequent questions we get in the FAQ.md + document. Study the COPYING file for distribution terms. @@ -38,7 +39,7 @@ GIT To download the latest source code off the GIT server, do this: - git clone https://github.com/curl/curl.git + git clone https://github.com/curl/curl (you will get a directory named curl created, filled with the source code) diff --git a/README.md b/README.md index 32a3c34fb0f2..69e8b937dc17 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,13 @@ SPDX-License-Identifier: curl # [![curl logo](https://curl.se/logo/curl-logo.svg)](https://curl.se/) -curl is a command-line tool for transferring data specified with URL syntax. +curl is a command-line 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. + Learn how to use curl by reading [the -manpage](https://curl.se/docs/manpage.html) or [everything +man page](https://curl.se/docs/manpage.html) or [everything curl](https://everything.curl.dev/). Find out how to install curl by reading [the INSTALL @@ -16,7 +20,7 @@ document](https://curl.se/docs/install.html). libcurl is the library curl is using to do its job. It is readily available to be used by your software. Read [the libcurl -manpage](https://curl.se/libcurl/c/libcurl.html) to learn how. +man page](https://curl.se/libcurl/c/libcurl.html) to learn how. ## Open Source @@ -46,7 +50,7 @@ Visit the [curl website](https://curl.se/) for the latest news and downloads. Download the latest source from the Git server: - git clone https://github.com/curl/curl.git + git clone https://github.com/curl/curl ## Security problems diff --git a/RELEASE-NOTES b/RELEASE-NOTES index 0930a2719e04..887ae11dda7b 100644 --- a/RELEASE-NOTES +++ b/RELEASE-NOTES @@ -1,338 +1,347 @@ -curl and libcurl 8.17.0 +curl and libcurl 8.18.0 - Public curl releases: 271 + Public curl releases: 272 Command line options: 273 curl_easy_setopt() options: 308 Public functions in libcurl: 100 - Contributors: 3519 + Contributors: 3562 This release includes the following changes: - o build: drop Heimdal support [267] - o build: drop the winbuild build system [81] - o krb5: drop support for Kerberos FTP [43] - o libssh2: up the minimum requirement to 1.9.0 [85] - o multi: add notifications API [250] - o progress: expand to use 6 characters per size [234] - o ssl: support Apple SecTrust configurations [240] - o tool_getparam: add --knownhosts [204] - o vssh: drop support for wolfSSH [58] - o wcurl: import v2025.09.27 [182] - o write-out: make %header{} able to output *all* occurrences of a header [25] + o build: drop support for VS2008 (Windows) [62] + o build: drop Windows CE / CeGCC support [69] + o gnutls: drop support for GnuTLS < 3.6.5 [167] + o gnutls: implement CURLOPT_CAINFO_BLOB [168] + o openssl: bump minimum OpenSSL version to 3.0.0 [60] This release includes the following bugfixes: - o ares: fix leak in tracing [91] - o asyn-ares: remove wrong comment about the callback argument [306] - o asyn-ares: use the duped hostname pointer for all calls [158] - o asyn-thrdd resolver: clear timeout when done [97] - o asyn-thrdd: drop pthread_cancel [30] - o autotools: add support for libgsasl auto-detection via pkg-config [112] - o autotools: capitalize 'Rustls' in the log output [106] - o autotools: fix duplicate `UNIX` and `BSD` flags in `buildinfo.txt` [113] - o autotools: fix silly mistake in clang detection for `buildinfo.txt` [114] - o autotools: make `--enable-code-coverage` support llvm/clang [79] - o aws-lc: re-enable large read-ahead with v1.61.0 again [16] - o base64: accept zero length argument to base64_encode [82] - o build: address some `-Weverything` warnings, update picky warnings [74] - o build: avoid overriding system `open` and `stat` symbols [141] - o build: avoid overriding system symbols for fopen functions [150] - o build: avoid overriding system symbols for socket functions [68] - o build: show llvm/clang in platform flags and `buildinfo.txt` [126] - o c-ares: when resolving failed, persist error [270] - o cf-h2-proxy: break loop on edge case [140] - o cf-ip-happy: mention unix domain path, not port number [161] - o cf-socket: always check Curl_cf_socket_peek() return code [198] - o cf-socket: check params and remove accept procondition [197] - o cf-socket: set FD_CLOEXEC on all sockets opened [273] - o cf-socket: tweak a memcpy() to read better [177] - o cf-socket: use the right byte order for ports in bindlocal [61] - o cfilter: unlink and discard [46] - o checksrc: allow disabling warnings on FIXME/TODO comments [324] - o checksrc: catch banned functions when preceded by `(` [146] - o checksrc: fix possible endless loop when detecting `BANNEDFUNC` [149] - o checksrc: fix possible endless loops/errors in the banned function logic [220] - o checksrc: fix to handle `)` predecing a banned function [229] - o checksrc: reduce directory-specific exceptions [228] - o CI.md: refresh [280] - o cmake/FindGSS: dedupe pkg-config module strings [277] - o cmake/FindGSS: drop wrong header check for GNU GSS [278] - o cmake/FindGSS: fix `pkg-config` fallback logic for CMake <3.16 [189] - o cmake/FindGSS: simplify/de-dupe lib setup [253] - o cmake/FindGSS: whitespace/formatting [268] - o cmake: add `CURL_CODE_COVERAGE` option [78] - o cmake: build the "all" examples source list dynamically [245] - o cmake: clang detection tidy-ups [116] - o cmake: drop exclamation in comment looking like a name [160] - o cmake: fix building docs when the base directory contains `.3` [18] - o cmake: minor Heimdal flavour detection fix [269] - o cmake: pre-fill three more type sizes on Windows [244] - o cmake: support building some complicated examples, build them in CI [235] - o cmake: use modern alternatives for `get_filename_component()` [102] - o cmake: use more `COMPILER_OPTIONS`, `LINK_OPTIONS` / `LINK_FLAGS` [152] - o cmdline-docs: extended, clarified, refreshed [28] - o cmdline-opts/_PROGRESS.md: explain the suffixes [154] - o configure: add "-mt" for pthread support on HP-UX [52] - o conn: fix hostname move on connection reuse [272] - o connect: remove redundant condition in shutdown start [289] - o cookie: avoid saving a cookie file if no transfer was done [11] - o cpool: make bundle->dest an array; fix UB [218] - o curl_easy_getinfo: error code on NULL arg [2] - o curl_mem_undef.h: limit to `CURLDEBUG` for non-memalloc overrides [19] - o curl_osslq: error out properly if BIO_ADDR_rawmake() fails [184] - o Curl_resolv: fix comment. 'entry' argument is not optional [187] - o curl_slist_append.md: clarify that a NULL pointer is not acceptable [72] - o curl_threads: delete WinCE fallback branch [233] - o CURLINFO_FTP_ENTRY_PATH.md: this is for SFTP as well [8] - o CURLOPT_COOKIEFILE.md: clarify when the cookies are loaded [159] - o CURLOPT_HEADER/WRITEFUNCTION.md: drop '* size' since size is always 1 [63] - o CURLOPT_MAXLIFETIME_CONN: make default 24 hours [10] - o CURLOPT_SSL_VERIFYHOST.md: add see-also to two other VERIFYHOST options [32] - o CURLOPT_TIMECONDITION.md: works for FILE and FTP as well [27] - o digest_sspi: fix two memory leaks in error branches [77] - o dist: do not distribute `CI.md` [29] - o docs/cmdline-opts: drop double quotes from GLOBBING and URL examples [238] - o docs/libcurl: clarify some timeout option behavior [15] - o docs/libcurl: remove ancient version references [7] - o docs/libcurl: use lowercase must [5] - o docs: expand on quoting rules for file names in SFTP quote [300] - o docs: fix/tidy code fences [87] - o doswin: CloseHandle the thread on shutdown [307] - o easy_getinfo: check magic, Curl_close safety [3] - o examples/sessioninfo: cast printf string mask length to int [232] - o examples/sessioninfo: do not disable security [255] - o examples/synctime: fix null termination assumptions [297] - o examples/synctime: make the sscanf not overflow the local buffer [252] - o examples/usercertinmem: avoid stripping const [247] - o examples: call `curl_global_cleanup()` where missing [323] - o examples: check more errors, fix cleanups, scope variables [318] - o examples: drop unused `curl/mprintf.h` includes [224] - o examples: fix build issues in 'complicated' examples [243] - o examples: fix two build issues surfaced with WinCE [223] - o examples: fix two issues found by CodeQL [35] - o examples: fix two more cases of `stat()` TOCTOU [147] - o examples: improve global init, error checks and returning errors [321] - o examples: return `curl_easy_perform()` results [322] - o form.md: drop reference to MANUAL [178] - o ftp: add extra buffer length check [195] - o ftp: fix ftp_do_more returning with *completep unset [122] - o ftp: fix port number range loop for PORT commands [66] - o ftp: fix the 213 scanner memchr buffer limit argument [196] - o ftp: improve fragile check for first digit > 3 [194] - o ftp: remove misleading comments [193] - o ftp: replace strstr() in ;type= handling [313] - o ftp: simplify the 150/126 size scanner [288] - o gnutls: check conversion of peer cert chain [275] - o gtls: avoid potential use of uninitialized variable in trace output [83] - o hostip: don't store negative resolves due unrelated errors [256] - o hostip: remove leftover INT_MAX check in Curl_dnscache_prune [88] - o http2: check push header names by length first [261] - o http2: cleanup pushed newhandle on fail [260] - o http2: ingress handling edge cases [259] - o http: handle user-defined connection headers [165] - o http: look for trailing 'type=' in ftp:// without strstr [315] - o http: make Content-Length parser more WHATWG [183] - o httpsrr: free old pointers when storing new [57] - o INSTALL-CMAKE.md: document useful build targets [215] - o INTERNALS: drop Winsock 2.2 from the dependency list [162] - o ip-happy: do not set unnecessary timeout [95] - o ip-happy: prevent event-based stall on retry [155] - o kerberos: bump minimum to 1.3 (2003-07-08), drop legacy logic [279] - o kerberos: drop logic for MIT Kerberos <1.2.3 (pre-2002) versions [285] - o kerberos: stop including `gssapi/gssapi_generic.h` [282] - o krb5: return appropriate error on send failures [22] - o krb5_gssapi: fix memory leak on error path [190] - o krb5_sspi: the chlg argument is NOT optional [200] - o ldap: avoid null ptr deref on failure [284] - o ldap: do not base64 encode zero length string [42] - o ldap: tidy-up types, fix error code confusion [191] - o lib1514: fix return code mixup [304] - o lib: drop unused include and duplicate guards [226] - o lib: fix build error and compiler warnings with verbose strings disabled [173] - o lib: remove personal names from comments [168] - o lib: SSL connection reuse [301] - o lib: stop NULL-checking conn->passwd and ->user [309] - o lib: upgrade/multiplex handling [136] - o libcurl-multi.md: added curl_multi_get_offt mention [53] - o libcurl-security.md: mention long-running connections [6] - o libssh/libssh2: reject quote command lines with too much data [299] - o libssh/sftp: fix resume corruption by avoiding O_APPEND with rresume [263] - o libssh2/sftp: fix resume corruption by avoiding O_APPEND with rresume [262] - o libssh2/sftp_realpath: change state consistently [185] - o libssh2: avoid risking using an uninitialized local struct field [209] - o libssh2: bail out on chgrp and chown number parsing errors [202] - o libssh2: clarify that sshp->path is always at least one byte [201] - o libssh2: drop two redundant null-terminations [26] - o libssh2: error check and null-terminate in ssh_state_sftp_readdir_link() [34] - o libssh2: fix EAGAIN return in ssh_state_auth_agent [290] - o libssh2: fix return code for EAGAIN [186] - o libssh2: use sockindex consistently [302] - o libssh: acknowledge SSH_AGAIN in the SFTP state machine [89] - o libssh: catch a resume point larger than the size [281] - o libssh: clarify myssh_block2waitfor [92] - o libssh: drop two unused assignments [104] - o libssh: error on bad chgrp number [71] - o libssh: error on bad chown number and store the value [64] - o libssh: fix range parsing error handling mistake [120] - o libssh: make atime and mtime cap the timestamp instead of wrap [283] - o libssh: react on errors from ssh_scp_read [24] - o libssh: return out of memory correctly if aprintf fails [60] - o Makefile.example: fix option order [231] - o Makefile.example: simplify and make it configurable [20] - o managen: ignore version mentions < 7.66.0 [55] - o managen: render better manpage references/links [54] - o managen: strict protocol check [109] - o managen: verify the options used in example lines [181] - o mbedtls: check result of setting ALPN [127] - o mbedtls: handle WANT_WRITE from mbedtls_ssl_read() [145] - o mdlinkcheck: reject URLs containing quotes [174] - o memdup0: handle edge case [241] - o multi.h: add CURLMINFO_LASTENTRY [51] - o multi_ev: remove unnecessary data check that confuses analysers [167] - o nghttp3: return NGHTTP3_ERR_CALLBACK_FAILURE from recv_header [227] - o ngtcp2: check error code on connect failure [13] - o ngtcp2: close just-opened QUIC stream when submit_request fails [222] - o ngtcp2: compare idle timeout in ms to avoid overflow [248] - o ngtcp2: fix early return [131] - o ngtcp2: fix handling of blocked stream data [236] - o ngtcp2: fix returns when TLS verify failed [251] - o noproxy: fix the IPV6 network mask pattern match [166] - o openldap: avoid indexing the result at -1 for blank responses [44] - o openldap: check ber_sockbuf_add_io() return code [163] - o openldap: check ldap_get_option() return codes [119] - o openldap: fix memory-leak in error path [287] - o openldap: fix memory-leak on oldap_do's exit path [286] - o openssl-quic: check results better [132] - o openssl-quic: handle error in SSL_get_stream_read_error_code [129] - o openssl-quic: ignore unexpected streams opened by server [176] - o openssl: call SSL_get_error() with proper error [207] - o openssl: clear retry flag on x509 error [130] - o openssl: fail the transfer if ossl_certchain() fails [23] - o openssl: fix build for v1.0.2 [225] - o openssl: fix peer certificate leak in channel binding [258] - o openssl: make the asn1_object_dump name null terminated [56] - o openssl: set io_need always [99] - o openssl: skip session resumption when verifystatus is set [230] - o os400: document threads handling in code. [254] - o OS400: fix a use-after-free/double-free case [142] - o osslq: set idle timeout to 0 [237] - o pingpong: remove two old leftover debug infof() calls - o pop3: function could get the ->transfer field wrong [292] - o pytest: skip specific tests for no-verbose builds [171] - o quic: fix min TLS version handling [14] - o quic: ignore EMSGSIZE on receive [4] - o quic: remove data_idle handling [311] - o quiche: fix possible leaks on teardown [205] - o quiche: fix verbose message when ip quadruple cannot be obtained. [128] - o quiche: handle tls fail correctly [266] - o quiche: when ingress processing fails, return that error code [103] - o runtests: tag tests that require curl verbose strings [172] - o rustls: fix clang-tidy warning [107] - o rustls: fix comment describing cr_recv() [117] - o rustls: pass the correct result to rustls_failf [242] - o rustls: typecast variable for safer trace output [69] - o rustls: use %zu for size_t in failf() format string [121] - o sasl: clear canceled mechanism instead of toggling it [41] - o schannel: assign result before using it [62] - o schannel_verify: fix mem-leak in Curl_verify_host [208] - o schannel_verify: use more human friendly error messages [96] - o setopt: accept *_SSL_VERIFYHOST set to 2L [31] - o setopt: allow CURLOPT_DNS_CACHE_TIMEOUT set to -1 [257] - o setopt: make CURLOPT_MAXREDIRS accept -1 (again) [1] - o smb: adjust buffer size checks [45] - o smb: transfer debugassert to real check [303] - o smtp: check EHLO responses case insensitively [50] - o socks: advance iobuf instead of reset [276] - o socks: deny server basic-auth if not configured [264] - o socks: handle error in verbose trace gracefully [94] - o socks: handle premature close [246] - o socks: make Curl_blockread_all return CURLcode [67] - o socks: rewwork, cleaning up socks state handling [135] - o socks_gssapi: make the gss_context a local variable [144] - o socks_gssapi: reject too long tokens [90] - o socks_gssapi: remove superfluous releases of the gss_recv_token [139] - o socks_gssapi: remove the forced "no protection" [143] - o socks_sspi: bail out on too long fields [137] - o socks_sspi: fix memory cleanup calls [40] - o socks_sspi: remove the enforced mode clearing [291] - o socks_sspi: restore non-blocking socket on error paths [48] - o socksd: remove --bindonly mention, there is no such option [305] - o ssl-sessions.md: mark option experimental [12] - o strerror: drop workaround for SalfordC win32 header bug [214] - o sws: fix checking `sscanf()` return value [17] - o sws: pass in socket reference to allow function to close it [298] - o tcp-nodelay.md: expand the documentation [153] - o telnet: ignore empty suboptions [86] - o telnet: make bad_option() consider NULL a bad option too [192] - o telnet: make printsub require another byte input [21] - o telnet: print DISPlay LOCation in printsub without mutating buffer [216] - o telnet: refuse IAC codes in content [111] - o telnet: return error if WSAEventSelect fails [180] - o telnet: return error on crazy TTYPE or XDISPLOC lengths [123] - o telnet: send failure logged but not returned [175] - o telnet: use pointer[0] for "unknown" option instead of pointer[i] [217] - o tests/server: drop pointless memory allocation overrides [219] - o tests/server: drop unsafe `open()` override in signal handler (Windows) [151] - o tftp: check and act on tftp_set_timeouts() returning error [38] - o tftp: check for trailing ";mode=" in URL without strstr [312] - o tftp: default timeout per block is now 15 seconds [156] - o tftp: error requests for blank filenames [296] - o tftp: handle tftp_multi_statemach() return code [65] - o tftp: pin the first used address [110] - o tftp: propagate expired timer from tftp_state_timeout() [39] - o tftp: return error if it hits an illegal state [138] - o tftp: return error when sendto() fails [59] - o thread: errno on thread creation [271] - o tidy-up: `fcntl.h` includes [98] - o tidy-up: assortment of small fixes [115] - o tidy-up: avoid using the reserved macro namespace [76] - o tidy-up: update MS links, allow long URLs via `checksrc` [73] - o tidy-up: URLs [101] - o time-cond.md: refer to the singular curl_getdate man page [148] - o TODO: fix a typo [93] - o TODO: remove already implemented or bad items [36] - o tool: fix exponential retry delay [47] - o tool_cb_hdr: fix fwrite check in header callback [49] - o tool_cb_hdr: size is always 1 [70] - o tool_doswin: fix to use curl socket functions [108] - o tool_filetime: replace cast with the fitting printf mask (Windows) [212] - o tool_getparam/set_rate: skip the multiplication on overflow [84] - o tool_getparam: always disable "lib-ids" for tracing [169] - o tool_getparam: make --fail and --fail-with-body override each other [293] - o tool_getparam: warn if provided header looks malformed [179] - o tool_msgs: make errorf() show if --show-error [294] - o tool_operate: improve wording in retry message [37] - o tool_operate: keep failed partial download for retry auto-resume [210] - o tool_operate: keep the progress meter for --out-null [33] - o tool_operate: retry on HTTP response codes 522 and 524 [317] - o tool_progress: handle possible integer overflows [164] - o tool_progress: make max5data() use an algorithm [170] - o transfer: avoid busy loop with tiny speed limit [100] - o transfer: reset retry count on each request [310] - o unit1323: sync time types and printf masks, drop casts [211] - o unit1664: drop casts, expand masks to full values [221] - o url: make Curl_init_userdefined return void [213] - o urldata: FILE is not a list-only protocol [9] - o urldata: make 'retrycount' a single byte [308] - o urldata: make redirect counter 16 bit [295] - o vauth/digest: improve the digest parser [203] - o vquic: fix idle-timeout checks (ms<-->ns), 64-bit log & honor 0=no-timeout [249] - o vquic: handling of io improvements [239] - o vquic: sending non-gso packets fix for EAGAIN [265] - o vtls: alpn setting, check proto parameter [134] - o vtls_int.h: clarify data_pending [124] - o vtls_scache: fix race condition [157] - o windows: replace `_beginthreadex()` with `CreateThread()` [80] - o windows: stop passing unused, optional argument for Win9x compatibility [75] - o windows: use consistent format when showing error codes [199] - o windows: use native error code types more [206] - o wolfssl: check BIO read parameters [133] - o wolfssl: fix error check in shutdown [105] - o wolfssl: no double get_error() detail [188] - o ws: clarify an error message [125] - o ws: fix some edge cases [274] - o ws: fix type conversion check [316] - o ws: reject curl_ws_recv called with NULL buffer with a buflen [118] + o _PROGRESS.md: add the E unit, mention kibibyte [24] + o alt-svc: more flexibility on same destination [298] + o altsvc: make it one malloc instead of three per entry [266] + o AmigaOS: increase minimum stack size for tool_main [137] + o apple-sectrust: always ask when `native_ca_store` is in use [162] + o asyn-ares: handle Curl_dnscache_mk_entry() OOM error [199] + o asyn-ares: remove hostname free on OOM [122] + o asyn-thrdd: fix Curl_async_getaddrinfo() on systems without getaddrinfo [265] + o asyn-thrdd: release rrname if ares_init_options fails [41] + o auth: always treat Curl_auth_ntlm_get() returning NULL as OOM [186] + o autotools: add nettle library detection via pkg-config (for GnuTLS) [178] + o autotools: drop autoconf <2.59 compatibility code (zz60-xc-ovr) [70] + o autotools: fix LargeFile feature display on Windows (after prev patch) [276] + o autotools: tidy-up `if` expressions [275] + o badwords: catch and fix threading-related words [320] + o badwords: fix issues found in scripts and other files [142] + o badwords: fix issues found in tests [156] + o build: add build-level `CURL_DISABLE_TYPECHECK` options [163] + o build: exclude clang prereleases from compiler warning options [154] + o build: replace `-pedantic` with `-Wpedantic` when supported [306] + o build: set `-Wno-format-signedness` [288] + o build: tidy-up MSVC CRT warning suppression macros [140] + o ccsidcurl: make curl_mime_data_ccsid() use the converted size [74] + o cf-https-connect: allocate ctx at first in cf_hc_create() [79] + o cf-socket: drop feature check for `IPV6_V6ONLY` on Windows [210] + o cf-socket: enable Win10 `TCP_KEEP*` options with old SDKs [323] + o cf-socket: limit use of `TCP_KEEP*` to Windows 10.0.16299+ at runtime [157] + o cf-socket: trace ignored errors [97] + o cfilters: make conn_forget_socket a private libssh function [109] + o checksrc.pl: detect assign followed by more than one space [26] + o cmake: adjust defaults for target platforms not supporting shared libs [35] + o cmake: define dependencies as `IMPORTED` interface targets [223] + o cmake: disable `CURL_CA_PATH` auto-detection if `USE_APPLE_SECTRUST=ON` [16] + o cmake: fix `ws2_32` reference in `curl-config.cmake` [201] + o cmake: honor `CURL_DISABLE_INSTALL` and `CURL_ENABLE_EXPORT_TARGET` [106] + o cmake: replace deprecated `OPENSSL_FOUND` with `OpenSSL_FOUND` [310] + o cmake: replace deprecated `PERL_FOUND` with `Perl_FOUND` [312] + o cmake: save and restore `CMAKE_MODULE_PATH` in `curl-config.cmake` [222] + o code: minor indent fixes before closing braces [107] + o CODE_STYLE.md: sync banned function list with checksrc.pl [243] + o compressed.md: might generate a huge amount of bytes [227] + o config-win32.h: delete obsolete, non-Windows comments [295] + o config-win32.h: drop unused/obsolete `CURL_HAS_OPENLDAP_LDAPSDK` [278] + o config2setopts: bail out if curl_url_get() returns OOM [102] + o config2setopts: exit if curl_url_set() fails on OOM [105] + o configure: delete unused variable [294] + o conncache: silence `-Wnull-dereference` on gcc 14 RISC-V 64 [17] + o conncontrol: reuse handling [170] + o connect: reshuffle Curl_timeleft_ms to avoid 'redundant condition' [100] + o connection: attached transfer count [228] + o cookie. return proper error on OOM [330] + o cookie: allocate the main struct once cookie is fine [259] + o cookie: only keep and use the canonical cleaned up path [256] + o cookie: propagate errors better, cleanup the internal API [118] + o cookie: return error on OOM [131] + o cookie: when parsing a cookie header, delay all allocations until okay [258] + o cshutdn: acknowledge FD_SETSIZE for shutdown descriptors [25] + o curl: fix progress meter in parallel mode [15] + o curl_fopen: do not pass invalid mode flags to `open()` on Windows [84] + o curl_gssapi: make sure Curl_gss_log_error() has an initialized buffer [257] + o curl_sasl: if redirected, require permission to use bearer [250] + o curl_sasl: make Curl_sasl_decode_mech compare case insensitively [160] + o curl_setup.h: document more funcs flagged by `_CRT_SECURE_NO_WARNINGS` [124] + o curl_setup.h: drop stray `#undef stat` (Windows) [103] + o curl_setup.h: drop superfluous parenthesis from `Curl_safefree` macro [242] + o curl_trc: delete unused DoH remains [272] + o CURLINFO: remove 'get' and 'get the' from each short desc [50] + o CURLINFO_SCHEME/PROTOCOL: they return the "scheme" for a "transfer" [48] + o CURLINFO_TLS_SSL_PTR.md: remove CURLINFO_TLS_SESSION text [49] + o CURLMOPT_SOCKETFUNCTION.md: fix the callback argument use [206] + o CURLOPT_ACCEPT_ENCODING.md: warn about the expansion [224] + o CURLOPT_FOLLOWLOCATION.md: s/Authentication:/Authorization:/ [283] + o CURLOPT_READFUNCTION.md: clarify the size of the buffer [47] + o CURLOPT_SSH_KEYFUNCTION.md: fix minor indent mistake in example + o curlx/fopen: replace open CRT functions their with `_s` counterparts (Windows) [204] + o curlx/multibyte: stop setting macros for non-Windows [226] + o curlx/strerr: use `strerror_s()` on Windows [75] + o curlx: limit use of system allocators to the minimum possible [169] + o curlx: replace `mbstowcs`/`wcstombs` with `_s` counterparts (Windows) [143] + o curlx: replace `sprintf` with `snprintf` [194] + o curlx: use curlx allocators in non-memdebug builds (Windows) [155] + o DEPRECATE: add CMake <3.18 deprecation for April 2026 [291] + o digest_sspi: fix a memory leak on error path [149] + o digest_sspi: properly free sspi identity [12] + o DISTROS.md: add OpenBSD [126] + o DISTROS: fix a Mageia URL + o DISTROS: remove broken URLs for buildroot + o doc: some returned in-memory data may not be altered [196] + o Dockerfile: update debian:bookworm-slim digest to e899040 [305] + o docs/libcurl: fix C formatting nits [207] + o docs: clarify how to do unix domain sockets with SOCKS proxy [240] + o docs: fix checksrc `EQUALSPACE` warnings [21] + o docs: fix time_posttransfer output unit as seconds [335] + o docs: mention umask need when curl creates files [56] + o docs: remove dead URLs + o docs: rename CURLcode variables to 'result' + o docs: spell it Rustls with a capital R [181] + o docs: switch more URLs to https:// [229] + o docs: use .example URLs for proxies + o docs: use mresult as variable name for CURLMcode + o example: fix formatting nits [232] + o examples/crawler: fix variable [92] + o examples/multi-uv: fix invalid req->data access [177] + o examples/threaded-ssl: delete in favor of `examples/threaded` [318] + o examples/threaded: fix race condition [101] + o examples: fix minor typo [203] + o examples: make functions/data static where missing [139] + o examples: tidy-up headers and includes [138] + o examples: use 64-bit `fstat` on Windows [301] + o FAQ/TODO/KNOWN_BUGS: convert to markdown [307] + o FAQ: fix hackerone URL + o file: do not pass invalid mode flags to `open()` on upload (Windows) [83] + o formdata: validate callback is non-NULL before use [267] + o ftp: make EPRT connections non-blocking [268] + o ftp: refactor a piece of code by merging the repeated part [40] + o ftp: remove #ifdef for define that is always defined [76] + o getenv: drop internal 1-to-1 wrapper [334] + o getinfo: improve perf in debug mode [99] + o gnutls: add PROFILE_MEDIUM as default [233] + o gnutls: report accurate error when TLS-SRP is not built-in [18] + o gtls: add return checks and optimize the code [2] + o gtls: Call keylog_close in cleanup + o gtls: skip session resumption when verifystatus is set + o h2/h3: handle methods with spaces [146] + o headers: add length argument to Curl_headers_push() [309] + o hostcheck: fail wildcard match if host starts with a dot [235] + o hostip: don't store negative lookup on OOM [61] + o hostip: make more functions return CURLcode [202] + o hostip: only store negative response for CURLE_COULDNT_RESOLVE_HOST [183] + o hsts: propagate and error out correctly on OOM [130] + o hsts: use one malloc instead of two per entry [263] + o http: acknowledge OOM errors from Curl_input_ntlm [185] + o http: avoid two strdup()s and do minor simplifications [144] + o http: error on OOM when creating range header [59] + o http: fix OOM exit in Curl_http_follow [179] + o http: handle oom error from Curl_input_digest() [192] + o http: replace atoi use in Curl_http_follow with curlx_str_number [65] + o http: return OOM errors from hsts properly [262] + o http: the :authority header should never contain user+password [147] + o http: unfold response headers earlier [277] + o idn: avoid allocations and wcslen on Windows [247] + o idn: clarify null-termination on Windows [324] + o idn: fix memory leak in `win32_ascii_to_idn()` [173] + o idn: use curlx allocators on Windows [165] + o imap: check buffer length before accessing it [308] + o imap: make sure Curl_pgrsSetDownloadSize() does not overflow [200] + o INSTALL-CMAKE.md: document static option defaults more [37] + o krb5: fix detecting channel binding feature [187] + o krb5_sspi: unify a part of error handling [80] + o ldap: call ldap_init() before setting the options [236] + o ldap: drop PP logic for old, unsupported, Windows SDKs [279] + o ldap: improve detection of Apple LDAP [174] + o ldap: provide version for "legacy" ldap as well [254] + o lib/sendf.h: forward declare two structs [221] + o lib: cleanup for some typos about spaces and code style [3] + o lib: create unitprotos.h in the builddir, not srcdir [322] + o lib: eliminate size_t casts [112] + o lib: error for OOM when extracting URL query [127] + o lib: fix formatting nits (part 2) [253] + o lib: fix formatting nits (part 3) [248] + o lib: fix formatting nits [215] + o lib: fix gssapi.h include on IBMi [55] + o lib: name the main CURLMcode variable 'mresult' [316] + o lib: refactor the type of funcs which have useless return and checks [1] + o lib: replace `_tcsncpy`/`wcsncpy`/`wcscpy` with `_s` counterparts (Windows) [164] + o lib: timer stats improvements [190] + o libssh2: add paths to error messages for quote commands [114] + o libssh2: cleanup ssh_force_knownhost_key_type [64] + o libssh2: consider strdup() failures OOM and return correctly [72] + o libssh2: replace atoi() in ssh_force_knownhost_key_type [63] + o libssh: fix state machine loop to progress as it should + o libssh: properly free sftp_attributes [153] + o libtests: replace `atoi()` with `curlx_str_number()` [120] + o limit-rate: add example using --limit-rate and --max-time together [89] + o localtime: detect thread-safe alternatives and use them [325] + o m4/sectrust: fix test(1) operator [4] + o manage: expand the 'libcurl support required' message [208] + o mbedtls: fix potential use of uninitialized `nread` [8] + o mbedtls: sync format across log messages [213] + o mbedtls_threadlock: avoid calloc, use array [244] + o mdlinkcheck: ignore IP numbers, allow '@' in raw URLs + o mdlinkcheck: only look for markdown links in markdown files [311] + o memdebug: add mutex for thread safety [184] + o memdebug: fix realloc logging [286] + o mk-ca-bundle.md: the file format docs URL is permaredirected [188] + o mk-ca-bundle.pl: default to SHA256 fingerprints with `-t` option [73] + o mk-ca-bundle.pl: use `open()` with argument list to replace backticks [71] + o mqtt: reject overly big messages [39] + o multi: make max_total_* members size_t [158] + o multi: remove MSTATE_TUNNELING [297] + o multi: simplify admin handle processing [189] + o multibyte: limit `curlx_convert_*wchar*()` functions to Unicode builds [135] + o ngtcp2+openssl: fix leak of session [172] + o ngtcp2: remove the unused Curl_conn_is_ngtcp2 function [85] + o noproxy: fix build on systems without IPv6 [264] + o noproxy: fix ipv6 handling [239] + o noproxy: replace atoi with curlx_str_number [67] + o openssl: exit properly on OOM when getting certchain [133] + o openssl: fix a potential memory leak of bio_out [150] + o openssl: fix a potential memory leak of params.cert [151] + o openssl: no verify failf message unless strict [166] + o openssl: release ssl_session if sess_reuse_cb fails [43] + o openssl: remove code handling default version [28] + o openssl: simplify `HAVE_KEYLOG_CALLBACK` guard [212] + o openssl: toggling CURLSSLOPT_NO_PARTIALCHAIN makes a different CA cache [313] + o OS400/ccsidcurl: fix curl_easy_setopt_ccsid for non-converted blobs [94] + o OS400/makefile.sh: fix shellcheck warning SC2038 [86] + o osslq: code readability [5] + o progress: show fewer digits [78] + o projects/README.md: Markdown fixes [148] + o pytest fixes and improvements [159] + o pytest: add tests using sshd [303] + o pytest: disable two H3 earlydata tests for all platforms (was: macOS) [116] + o pytest: do not ignore server issues [329] + o pytest: fix and improve reliability [251] + o pytest: improve stragglers [252] + o pytest: quiche flakiness [280] + o pytest: skip H2 tests if feature missing from curl [46] + o quiche: use client writer [255] + o ratelimit: redesign [209] + o rtmp: fix double-free on URL parse errors [27] + o rtmp: precaution for a potential integer truncation [54] + o rtmp: stop redefining `setsockopt` system symbol on Windows [211] + o runner.pm: run memanalyzer as a Perl module [260] + o runtests: add options to set minimum number of tests, use them [302] + o runtests: detect bad libssh differently for test 1459 [11] + o runtests: drop Python 2 support remains [45] + o runtests: enable torture testing with threaded resolver [176] + o runtests: improve XML prolog check, enable `-w` permanently, fix two tests [231] + o runtests: make memanalyzer a Perl module (for 1.1-2x speed-up per test run) [238] + o rustls: fix a potential memory issue [81] + o rustls: minor adjustment of sizeof() [38] + o rustls: simplify init err path [219] + o rustls: verify that verifier_builder is not NULL [220] + o schannel: cap the maximum allowed size for loading cert [274] + o schannel: fix memory leak of cert_store_path on four error paths [23] + o schannel: replace atoi() with curlx_str_number() [119] + o schannel: use Win8 `CERT_NAME_SEARCH_ALL_NAMES_FLAG` with old SDKs [321] + o schannel_verify: fix a memory leak of cert_context [152] + o scripts: fix shellcheck SC2046 warnings [90] + o scripts: use end-of-options marker in `find -exec` commands [87] + o setopt: disable CURLOPT_HAPROXY_CLIENT_IP on NULL [30] + o setopt: when setting bad protocols, don't store them [9] + o sftp: fix range downloads in both SSH backends [82] + o slist: constify Curl_slist_append_nodup() string argument [195] + o smb: fix a size check to be overflow safe [161] + o socks_sspi: use free() not FreeContextBuffer() [93] + o speedcheck: do not trigger low speed cancel on transfers with CURL_READFUNC_PAUSE [113] + o speedlimit: also reset on send unpausing [197] + o src: fix formatting nits [246] + o ssh: tracing and better pollset handling [230] + o sspi: fix memory leaks on error paths in `Curl_create_sspi_identity()` [237] + o sws: fix binding to unix socket on Windows [214] + o synctime: tidy up, make it work on all platforms [269] + o telnet: replace atoi for BINARY handling with curlx_str_number [66] + o TEST-SUITE.md: correct the man page's path [136] + o test07_22: fix flakiness [95] + o test1475: consistently use %CR in headers [234] + o test1498: disable 'HTTP PUT from stdin' test on Windows [115] + o test2045: replace HTML multi-line comment markup with `#` comments [36] + o test318: tweak the name a little + o test3207: enable memdebug for this test again [249] + o test363: delete stray character (typo) from a section tag [52] + o test568: fix codespell, catch it next time early in CI [299] + o test568: remove what looks like an email and a URL [304] + o test787: fix possible typo `&` -> `%` in curl option [241] + o tests/data: move `--libcurl` output to external data files [34] + o tests/data: replace hard-coded test numbers with `%TESTNUMBER` [33] + o tests/data: support using native newlines on disk, drop `.gitattributes` [91] + o tests/server: do not fall back to original data file in `test2fopen()` [32] + o tests/server: fix initialization on Windows Vista+ [216] + o tests/server: replace `atoi()` and `atol()` with `curlx_str_number()` [110] + o tests: add `%AMP` macro, use it in two tests [245] + o tests: add a standard log line for alloc failures [319] + o tests: allow 2500-2503 to use ~2MB malloc [31] + o tests: fix formatting nits [225] + o tests: rename CURLMcode variables to mresult + o tftp: release filename if conn_get_remote_addr fails [42] + o tftpd: fix/tidy up `open()` mode flags [57] + o tidy-up: avoid `(())`, clang-format fixes and more [141] + o tidy-up: move `CURL_UNCONST()` out from macro `curl_unicodefree()` [121] + o tidy-up: URLs (cont.) and mdlinkcheck [285] + o tidy-up: URLs [182] + o TODO: remove a mandriva.com reference + o tool: consider (some) curl_easy_setopt errors fatal [7] + o tool: log when loading .curlrc in verbose mode [191] + o tool_cfgable: free ssl-sessions at exit [123] + o tool_doswin: clear pointer when thread takes ownership [198] + o tool_getparam: verify that a file exists for some options [134] + o tool_help: add checks to avoid unsigned wrap around [14] + o tool_ipfs: check return codes better [20] + o tool_msgs: make voutf() use stack instead of heap [125] + o tool_operate: exit on curl_share_setopt errors [108] + o tool_operate: fix a case of ignoring return code in operate() [128] + o tool_operate: fix case of ignoring return code in single_transfer [129] + o tool_operate: remove redundant condition [19] + o tool_operate: return error for OOM in append2query [217] + o tool_operate: use curlx_str_number instead of atoi [68] + o tool_paramhlp: refuse --proto remove all protocols [10] + o tool_urlglob: acknowledge OOM in peek_ipv6 [175] + o tool_urlglob: clean up used memory on errors better [44] + o tool_urlglob: support globs as long as config line lengths [282] + o tool_writeout: bail out proper on OOM [104] + o url: fix return code for OOM in parse_proxy() [193] + o url: if curl_url_get() fails due to OOM, error out properly [205] + o url: if OOM in parse_proxy() return error [132] + o urlapi: fix mem-leaks in curl_url_get error paths [22] + o urlapi: handle OOM properly when setting URL [180] + o verify-release: update to avoid shellcheck warning SC2034 [88] + o vquic-tls/gnutls: call Curl_gtls_verifyserver unconditionally [96] + o vquic: do not pass invalid mode flags to `open()` (Windows) [58] + o vquic: do_sendmsg full init [171] + o vquic: ignore 0-length UDP packets [336] + o vtls: fix CURLOPT_CAPATH use [51] + o vtls: handle possible malicious certs_num from peer [53] + o vtls: pinned key check [98] + o wcurl: import v2025.11.09 [29] + o windows: assume `USE_WIN32_LARGE_FILES` [292] + o windows: use `_strdup()` instead of `strdup()` where missing [145] + o wolfSSL: able to differentiate between IP and DNS in alt names [13] + o wolfssl: avoid NULL dereference in OOM situation [77] + o wolfssl: fix a potential memory leak of session [6] + o wolfssl: fix cipher list, skip 5.8.4 regression [117] + o wolfssl: fix possible assert with `!HAVE_NO_EX` wolfSSL builds [261] + o wolfssl: proof use of wolfSSL_i2d_SSL_SESSION [314] + o wolfssl: simplify wssl_send_earlydata [111] This release includes the following known bugs: @@ -344,352 +353,347 @@ For all changes ever done in curl: Planned upcoming removals include: - o Builds using VS2008 - o OpenSSL 1.x support o OpenSSL-QUIC + o RTMP support o Support for c-ares versions before 1.16.0 o Support for Windows XP/2003 - o Windows CE support See https://curl.se/dev/deprecate.html This release would not have looked like this without help, code, reports and advice from friends like these: - Adam Light, Alice Lee Poetics, Andrei Kurushin, Andrew Kirillov, - Andrew Olsen, BobodevMm on github, Christian Schmitz, Dan Fandrich, - Daniel Stenberg, Daniel Terhorst-North, dependabot[bot], - divinity76 on github, Emilio Pozuelo Monfort, Emre Çalışkan, Ethan Everett, - Evgeny Grin (Karlson2k), fds242 on github, Harry Sintonen, Howard Chu, - Ignat Loskutov, Javier Blazquez, Jicea, jmaggard10 on github, - Johannes Schindelin, Joseph Birr-Pixton, Joshua Rogers, kapsiR on github, - kuchara on github, Marcel Raad, Michael Osipov, Michał Petryka, - Mitchell Blank Jr, Mohamed Daahir, Nir Azkiel, Patrick Monnerat, - plv1313 on github, Pocs Norbert, Ray Satiro, renovate[bot], - rinsuki on github, Sakthi SK, Samuel Dionne-Riel, Samuel Henrique, - Stanislav Fort, Stefan Eissing, tkzv on github, Viktor Szakats - (47 contributors) + Aleksandr Sergeev, Aleksei Bavshin, Andrew Kirillov, + anonymous237 on hackerone, BANADDA, boingball, Brad King, bttrfl on github, + Christian Schmitz, Dan Fandrich, Daniel McCarney, Daniel Stenberg, + Denis Goleshchikhin, Deniz Parlak, dependabot[bot], Fabian Keil, + Fd929c2CE5fA on github, ffath-vo on github, Gabriel Marin, + Georg Schulz-Allgaier, Gisle Vanem, Greg Hudson, Harry Sintonen, Jeff King, + Jiyong Yang, John Haugabook, Juliusz Sosinowicz, Kai Pastor, + Leonardo Taccari, letshack9707 on hackerone, Marc Aldorasi, Marcel Raad, + Max Faxälv, nait-furry, ncaklovic on github, Nick Korepanov, + Omdahake on github, Patrick Monnerat, pelioro on hackerone, Ray Satiro, + renovate[bot], Robert W. Van Kirk, Samuel Henrique, Sergey Katsubo, + st751228051 on github, Stanislav Fort, Stefan Eissing, Sunny, Theo Buehler, + Thomas Klausner, Viktor Szakats, Wesley Moore, Xiaoke Wang, Yedaya Katsman, + Yuhao Jiang, yushicheng7788 on github + (56 contributors) References to bug reports and discussions on issues: - [1] = https://curl.se/bug/?i=18571 - [2] = https://curl.se/bug/?i=18512 - [3] = https://curl.se/bug/?i=18511 - [4] = https://curl.se/bug/?i=18505 - [5] = https://curl.se/bug/?i=18570 - [6] = https://curl.se/bug/?i=18533 - [7] = https://curl.se/bug/?i=18530 - [8] = https://curl.se/bug/?i=18531 - [9] = https://curl.se/bug/?i=18525 - [10] = https://curl.se/bug/?i=18527 - [11] = https://curl.se/bug/?i=18621 - [12] = https://curl.se/bug/?i=18523 - [13] = https://curl.se/bug/?i=18521 - [14] = https://curl.se/bug/?i=18518 - [15] = https://curl.se/bug/?i=18569 - [16] = https://curl.se/bug/?i=18568 - [17] = https://curl.se/bug/?i=18565 - [18] = https://curl.se/bug/?i=18560 - [19] = https://curl.se/bug/?i=18510 - [20] = https://curl.se/bug/?i=18554 - [21] = https://curl.se/bug/?i=18618 - [22] = https://curl.se/bug/?i=18561 - [23] = https://curl.se/bug/?i=18646 - [24] = https://curl.se/bug/?i=18616 - [25] = https://curl.se/bug/?i=18491 - [26] = https://curl.se/bug/?i=18606 - [27] = https://curl.se/bug/?i=18551 - [28] = https://curl.se/bug/?i=18550 - [29] = https://curl.se/bug/?i=18549 - [30] = https://curl.se/bug/?i=18532 - [31] = https://curl.se/mail/lib-2025-09/0031.html - [32] = https://curl.se/bug/?i=18548 - [33] = https://curl.se/bug/?i=18607 - [34] = https://curl.se/bug/?i=18598 - [35] = https://curl.se/bug/?i=18605 - [36] = https://curl.se/bug/?i=18542 - [37] = https://curl.se/bug/?i=18604 - [38] = https://curl.se/bug/?i=18603 - [39] = https://curl.se/bug/?i=18574 - [40] = https://curl.se/bug/?i=18587 - [41] = https://curl.se/bug/?i=18573 - [42] = https://curl.se/bug/?i=18602 - [43] = https://curl.se/bug/?i=18577 - [44] = https://curl.se/bug/?i=18600 - [45] = https://curl.se/bug/?i=18599 - [46] = https://curl.se/bug/?i=18596 - [47] = https://curl.se/bug/?i=18591 - [48] = https://curl.se/bug/?i=18592 - [49] = https://curl.se/bug/?i=18593 - [50] = https://curl.se/bug/?i=18588 - [51] = https://curl.se/bug/?i=18578 - [52] = https://curl.se/bug/?i=18585 - [53] = https://curl.se/bug/?i=18579 - [54] = https://curl.se/bug/?i=18580 - [55] = https://curl.se/bug/?i=18583 - [56] = https://curl.se/bug/?i=18647 - [57] = https://curl.se/bug/?i=18631 - [58] = https://curl.se/bug/?i=18700 - [59] = https://curl.se/bug/?i=18643 - [60] = https://curl.se/bug/?i=18637 - [61] = https://curl.se/bug/?i=18641 - [62] = https://curl.se/bug/?i=18642 - [63] = https://curl.se/bug/?i=18640 - [64] = https://curl.se/bug/?i=18639 - [65] = https://curl.se/bug/?i=18638 - [66] = https://curl.se/bug/?i=18636 - [67] = https://curl.se/bug/?i=18635 - [68] = https://curl.se/bug/?i=18503 - [69] = https://curl.se/bug/?i=18628 - [70] = https://curl.se/bug/?i=18630 - [71] = https://curl.se/bug/?i=18629 - [72] = https://curl.se/bug/?i=18627 - [73] = https://curl.se/bug/?i=18626 - [74] = https://curl.se/bug/?i=18477 - [75] = https://curl.se/bug/?i=18490 - [76] = https://curl.se/bug/?i=18482 - [77] = https://curl.se/bug/?i=18488 - [78] = https://curl.se/bug/?i=18468 - [79] = https://curl.se/bug/?i=18473 - [80] = https://curl.se/bug/?i=18451 - [81] = https://curl.se/bug/?i=18040 - [82] = https://curl.se/bug/?i=18617 - [83] = https://curl.se/bug/?i=18620 - [84] = https://curl.se/bug/?i=18624 - [85] = https://curl.se/bug/?i=18612 - [86] = https://curl.se/bug/?i=18899 - [87] = https://curl.se/bug/?i=18707 - [88] = https://curl.se/bug/?i=18680 - [89] = https://curl.se/bug/?i=18740 - [90] = https://curl.se/bug/?i=18681 - [91] = https://curl.se/bug/?i=18251 - [92] = https://curl.se/bug/?i=18739 - [93] = https://curl.se/bug/?i=18788 - [94] = https://curl.se/bug/?i=18722 - [95] = https://curl.se/bug/?i=18767 - [96] = https://curl.se/bug/?i=18737 - [97] = https://curl.se/bug/?i=18769 - [98] = https://curl.se/bug/?i=18782 - [99] = https://curl.se/bug/?i=18733 - [100] = https://curl.se/bug/?i=18732 - [101] = https://curl.se/bug/?i=18689 - [102] = https://curl.se/bug/?i=18688 - [103] = https://curl.se/bug/?i=18730 - [104] = https://curl.se/bug/?i=18684 - [105] = https://curl.se/bug/?i=18729 - [106] = https://curl.se/bug/?i=18671 - [107] = https://curl.se/bug/?i=18670 - [108] = https://curl.se/bug/?i=18633 - [109] = https://curl.se/bug/?i=18675 - [110] = https://curl.se/bug/?i=18658 - [111] = https://curl.se/bug/?i=18657 - [112] = https://curl.se/bug/?i=18669 - [113] = https://curl.se/bug/?i=18667 - [114] = https://curl.se/bug/?i=18666 - [115] = https://curl.se/bug/?i=18664 - [116] = https://curl.se/bug/?i=18659 - [117] = https://curl.se/bug/?i=18728 - [118] = https://curl.se/bug/?i=18656 - [119] = https://curl.se/bug/?i=18653 - [120] = https://curl.se/bug/?i=18652 - [121] = https://curl.se/bug/?i=18651 - [122] = https://curl.se/bug/?i=18650 - [123] = https://curl.se/bug/?i=18648 - [124] = https://curl.se/bug/?i=18644 - [125] = https://curl.se/bug/?i=18654 - [126] = https://curl.se/bug/?i=18645 - [127] = https://curl.se/bug/?i=18727 - [128] = https://curl.se/bug/?i=18726 - [129] = https://curl.se/bug/?i=18725 - [130] = https://curl.se/bug/?i=18724 - [131] = https://curl.se/bug/?i=18723 - [132] = https://curl.se/bug/?i=18720 - [133] = https://curl.se/bug/?i=18718 - [134] = https://curl.se/bug/?i=18717 - [135] = https://curl.se/bug/?i=18401 - [136] = https://curl.se/bug/?i=18227 - [137] = https://curl.se/bug/?i=18719 - [138] = https://curl.se/bug/?i=18894 - [139] = https://curl.se/bug/?i=18714 - [140] = https://curl.se/bug/?i=18715 - [141] = https://curl.se/bug/?i=18776 - [142] = https://curl.se/bug/?i=18713 - [143] = https://curl.se/bug/?i=18712 - [144] = https://curl.se/bug/?i=18711 - [145] = https://curl.se/bug/?i=18682 - [146] = https://curl.se/bug/?i=18779 - [147] = https://curl.se/bug/?i=18778 - [148] = https://curl.se/bug/?i=18816 - [149] = https://curl.se/bug/?i=18775 - [150] = https://curl.se/bug/?i=18510 - [151] = https://curl.se/bug/?i=18774 - [152] = https://curl.se/bug/?i=18762 - [153] = https://curl.se/bug/?i=18811 - [154] = https://curl.se/bug/?i=18817 - [155] = https://curl.se/bug/?i=18815 - [156] = https://curl.se/bug/?i=18893 - [157] = https://curl.se/bug/?i=18806 - [158] = https://curl.se/bug/?i=18980 - [159] = https://curl.se/bug/?i=18924 - [160] = https://curl.se/bug/?i=18810 - [161] = https://curl.se/bug/?i=18749 - [162] = https://curl.se/bug/?i=18808 - [163] = https://curl.se/bug/?i=18747 - [164] = https://curl.se/bug/?i=18744 - [165] = https://curl.se/bug/?i=18662 - [166] = https://curl.se/bug/?i=18891 - [167] = https://curl.se/bug/?i=18804 - [168] = https://curl.se/bug/?i=18803 - [169] = https://curl.se/bug/?i=18805 - [170] = https://curl.se/bug/?i=18807 - [171] = https://curl.se/bug/?i=18801 - [172] = https://curl.se/bug/?i=18800 - [173] = https://curl.se/bug/?i=18799 - [174] = https://curl.se/bug/?i=18889 - [175] = https://curl.se/bug/?i=18887 - [176] = https://curl.se/bug/?i=18780 - [177] = https://curl.se/bug/?i=18787 - [178] = https://curl.se/bug/?i=18790 - [179] = https://curl.se/bug/?i=18793 - [180] = https://curl.se/bug/?i=18886 - [181] = https://curl.se/bug/?i=18884 - [182] = https://curl.se/bug/?i=18754 - [183] = https://curl.se/bug/?i=18921 - [184] = https://curl.se/bug/?i=18878 - [185] = https://curl.se/bug/?i=18875 - [186] = https://curl.se/bug/?i=18874 - [187] = https://curl.se/bug/?i=18979 - [188] = https://curl.se/bug/?i=18940 - [189] = https://curl.se/bug/?i=18932 - [190] = https://curl.se/bug/?i=18976 - [191] = https://curl.se/bug/?i=18888 - [192] = https://curl.se/bug/?i=18873 - [193] = https://curl.se/bug/?i=18871 - [194] = https://curl.se/bug/?i=18870 - [195] = https://curl.se/bug/?i=18869 - [196] = https://curl.se/bug/?i=18867 - [197] = https://curl.se/bug/?i=18882 - [198] = https://curl.se/bug/?i=18862 - [199] = https://curl.se/bug/?i=18877 - [200] = https://curl.se/bug/?i=18865 - [201] = https://curl.se/bug/?i=18864 - [202] = https://curl.se/bug/?i=18863 - [203] = https://curl.se/bug/?i=18975 - [204] = https://curl.se/bug/?i=18859 - [205] = https://curl.se/bug/?i=18880 - [206] = https://curl.se/bug/?i=18868 - [207] = https://curl.se/bug/?i=18872 - [208] = https://curl.se/bug/?i=18972 - [209] = https://curl.se/bug/?i=19043 - [210] = https://curl.se/bug/?i=18035 - [211] = https://curl.se/bug/?i=18860 - [212] = https://curl.se/bug/?i=18858 - [213] = https://curl.se/bug/?i=18855 - [214] = https://curl.se/bug/?i=18857 - [215] = https://curl.se/bug/?i=18927 - [216] = https://curl.se/bug/?i=18852 - [217] = https://curl.se/bug/?i=18851 - [218] = https://curl.se/bug/?i=18850 - [219] = https://curl.se/bug/?i=18922 - [220] = https://curl.se/bug/?i=18845 - [221] = https://curl.se/bug/?i=18838 - [222] = https://curl.se/bug/?i=18904 - [223] = https://curl.se/bug/?i=18843 - [224] = https://curl.se/bug/?i=18842 - [225] = https://curl.se/bug/?i=18841 - [226] = https://curl.se/bug/?i=18839 - [227] = https://curl.se/bug/?i=18904 - [228] = https://curl.se/bug/?i=18823 - [229] = https://curl.se/bug/?i=18836 - [230] = https://curl.se/bug/?i=18902 - [231] = https://curl.se/bug/?i=18835 - [232] = https://curl.se/bug/?i=18918 - [233] = https://curl.se/bug/?i=19015 - [234] = https://curl.se/bug/?i=18828 - [235] = https://curl.se/bug/?i=18909 - [236] = https://curl.se/bug/?i=18905 - [237] = https://curl.se/bug/?i=18907 - [238] = https://curl.se/bug/?i=18829 - [239] = https://curl.se/bug/?i=18812 - [240] = https://curl.se/bug/?i=18703 - [241] = https://curl.se/bug/?i=18966 - [242] = https://curl.se/bug/?i=18961 - [243] = https://curl.se/bug/?i=18914 - [244] = https://curl.se/bug/?i=19013 - [245] = https://curl.se/bug/?i=18911 - [246] = https://curl.se/bug/?i=18883 - [247] = https://curl.se/bug/?i=18908 - [248] = https://curl.se/bug/?i=18903 - [249] = https://curl.se/bug/?i=18903 - [250] = https://curl.se/bug/?i=18432 - [251] = https://curl.se/bug/?i=18881 - [252] = https://curl.se/bug/?i=18890 - [253] = https://curl.se/bug/?i=19012 - [254] = https://curl.se/bug/?i=18967 - [255] = https://curl.se/bug/?i=18969 - [256] = https://curl.se/bug/?i=18953 - [257] = https://curl.se/bug/?i=18959 - [258] = https://hackerone.com/reports/3373640 - [259] = https://curl.se/bug/?i=18933 - [260] = https://curl.se/bug/?i=18931 - [261] = https://curl.se/bug/?i=18930 - [262] = https://curl.se/bug/?i=18952 - [263] = https://curl.se/bug/?i=18952 - [264] = https://curl.se/bug/?i=18937 - [265] = https://curl.se/bug/?i=18936 - [266] = https://curl.se/bug/?i=18934 - [267] = https://curl.se/bug/?i=18928 - [268] = https://curl.se/bug/?i=18957 - [269] = https://curl.se/bug/?i=18951 - [270] = https://curl.se/bug/?i=18999 - [271] = https://curl.se/bug/?i=18998 - [272] = https://curl.se/bug/?i=18995 - [273] = https://curl.se/bug/?i=18968 - [274] = https://curl.se/bug/?i=18965 - [275] = https://curl.se/bug/?i=18964 - [276] = https://curl.se/bug/?i=18938 - [277] = https://curl.se/bug/?i=18994 - [278] = https://curl.se/bug/?i=18993 - [279] = https://curl.se/bug/?i=18992 - [280] = https://curl.se/bug/?i=18973 - [281] = https://curl.se/bug/?i=19044 - [282] = https://curl.se/bug/?i=18990 - [283] = https://curl.se/bug/?i=18989 - [284] = https://curl.se/bug/?i=18988 - [285] = https://curl.se/bug/?i=18978 - [286] = https://curl.se/bug/?i=18986 - [287] = https://curl.se/bug/?i=18985 - [288] = https://curl.se/bug/?i=18984 - [289] = https://curl.se/bug/?i=19079 - [290] = https://curl.se/bug/?i=19042 - [291] = https://curl.se/bug/?i=19040 - [292] = https://curl.se/bug/?i=19039 - [293] = https://curl.se/bug/?i=19029 - [294] = https://curl.se/bug/?i=19035 - [295] = https://curl.se/bug/?i=19072 - [296] = https://curl.se/bug/?i=19033 - [297] = https://curl.se/bug/?i=19032 - [298] = https://curl.se/bug/?i=19031 - [299] = https://curl.se/bug/?i=19030 - [300] = https://curl.se/bug/?i=19025 - [301] = https://curl.se/bug/?i=19006 - [302] = https://curl.se/bug/?i=19004 - [303] = https://curl.se/bug/?i=19003 - [304] = https://curl.se/bug/?i=19027 - [305] = https://curl.se/bug/?i=19026 - [306] = https://curl.se/bug/?i=19014 - [307] = https://curl.se/bug/?i=18996 - [308] = https://curl.se/bug/?i=19071 - [309] = https://curl.se/bug/?i=19059 - [310] = https://curl.se/bug/?i=18926 - [311] = https://curl.se/bug/?i=19060 - [312] = https://curl.se/bug/?i=19070 - [313] = https://curl.se/bug/?i=19069 - [315] = https://curl.se/bug/?i=19065 - [316] = https://curl.se/bug/?i=19017 - [317] = https://curl.se/bug/?i=16143 - [318] = https://curl.se/bug/?i=19055 - [321] = https://curl.se/bug/?i=19053 - [322] = https://curl.se/bug/?i=19052 - [323] = https://curl.se/bug/?i=19051 - [324] = https://curl.se/bug/?i=19048 + [1] = https://curl.se/bug/?i=19386 + [2] = https://curl.se/bug/?i=19366 + [3] = https://curl.se/bug/?i=19370 + [4] = https://curl.se/bug/?i=19371 + [5] = https://curl.se/bug/?i=19394 + [6] = https://curl.se/bug/?i=19555 + [7] = https://curl.se/bug/?i=19385 + [8] = https://curl.se/bug/?i=19393 + [9] = https://curl.se/bug/?i=19389 + [10] = https://curl.se/bug/?i=19388 + [11] = https://curl.se/bug/?i=19557 + [12] = https://curl.se/bug/?i=19426 + [13] = https://curl.se/bug/?i=19364 + [14] = https://curl.se/bug/?i=19377 + [15] = https://curl.se/bug/?i=19383 + [16] = https://curl.se/bug/?i=19380 + [17] = https://curl.se/bug/?i=19378 + [18] = https://curl.se/bug/?i=19365 + [19] = https://curl.se/bug/?i=19381 + [20] = https://curl.se/bug/?i=19382 + [21] = https://curl.se/bug/?i=19379 + [22] = https://curl.se/bug/?i=19440 + [23] = https://curl.se/bug/?i=19423 + [24] = https://curl.se/bug/?i=19502 + [25] = https://curl.se/bug/?i=19439 + [26] = https://curl.se/bug/?i=19375 + [27] = https://curl.se/bug/?i=19438 + [28] = https://curl.se/bug/?i=19354 + [29] = https://curl.se/bug/?i=19430 + [30] = https://curl.se/bug/?i=19434 + [31] = https://curl.se/bug/?i=19716 + [32] = https://curl.se/bug/?i=19429 + [33] = https://curl.se/bug/?i=19427 + [34] = https://curl.se/bug/?i=19799 + [35] = https://curl.se/bug/?i=19420 + [36] = https://curl.se/bug/?i=19498 + [37] = https://curl.se/bug/?i=19419 + [38] = https://hackerone.com/reports/3427460 + [39] = https://curl.se/bug/?i=19415 + [40] = https://curl.se/bug/?i=19411 + [41] = https://curl.se/bug/?i=19410 + [42] = https://curl.se/bug/?i=19409 + [43] = https://curl.se/bug/?i=19405 + [44] = https://curl.se/bug/?i=19614 + [45] = https://curl.se/bug/?i=19544 + [46] = https://curl.se/bug/?i=19412 + [47] = https://curl.se/bug/?i=19402 + [48] = https://curl.se/bug/?i=19403 + [49] = https://curl.se/bug/?i=19404 + [50] = https://curl.se/bug/?i=19406 + [51] = https://curl.se/bug/?i=19401 + [52] = https://curl.se/bug/?i=19490 + [53] = https://curl.se/bug/?i=19397 + [54] = https://curl.se/bug/?i=19399 + [55] = https://curl.se/bug/?i=19336 + [56] = https://curl.se/bug/?i=19396 + [57] = https://curl.se/bug/?i=19671 + [58] = https://curl.se/bug/?i=19670 + [59] = https://curl.se/bug/?i=19630 + [60] = https://curl.se/bug/?i=18330 + [61] = https://curl.se/bug/?i=19484 + [62] = https://curl.se/bug/?i=17931 + [63] = https://curl.se/bug/?i=19479 + [64] = https://curl.se/bug/?i=19479 + [65] = https://curl.se/bug/?i=19478 + [66] = https://curl.se/bug/?i=19477 + [67] = https://curl.se/bug/?i=19475 + [68] = https://curl.se/bug/?i=19480 + [69] = https://curl.se/bug/?i=17927 + [70] = https://curl.se/bug/?i=19464 + [71] = https://curl.se/bug/?i=19461 + [72] = https://curl.se/bug/?i=19791 + [73] = https://curl.se/bug/?i=19359 + [74] = https://curl.se/bug/?i=19465 + [75] = https://curl.se/bug/?i=19646 + [76] = https://curl.se/bug/?i=19463 + [77] = https://curl.se/bug/?i=19459 + [78] = https://curl.se/bug/?i=19431 + [79] = https://curl.se/bug/?i=19454 + [80] = https://curl.se/bug/?i=19452 + [81] = https://curl.se/bug/?i=19425 + [82] = https://curl.se/bug/?i=19460 + [83] = https://curl.se/bug/?i=19647 + [84] = https://curl.se/bug/?i=19645 + [85] = https://curl.se/bug/?i=19725 + [86] = https://curl.se/bug/?i=19451 + [87] = https://curl.se/bug/?i=19450 + [88] = https://curl.se/bug/?i=19449 + [89] = https://curl.se/bug/?i=19473 + [90] = https://curl.se/bug/?i=19432 + [91] = https://curl.se/bug/?i=19398 + [92] = https://curl.se/bug/?i=19446 + [93] = https://curl.se/bug/?i=19445 + [94] = https://curl.se/bug/?i=19444 + [95] = https://curl.se/bug/?i=19530 + [96] = https://curl.se/bug/?i=19531 + [97] = https://curl.se/bug/?i=19520 + [98] = https://curl.se/bug/?i=19529 + [99] = https://curl.se/bug/?i=19525 + [100] = https://curl.se/bug/?i=19523 + [101] = https://curl.se/bug/?i=19524 + [102] = https://curl.se/bug/?i=19518 + [103] = https://curl.se/bug/?i=19519 + [104] = https://curl.se/bug/?i=19667 + [105] = https://curl.se/bug/?i=19517 + [106] = https://curl.se/bug/?i=19144 + [107] = https://curl.se/bug/?i=19512 + [108] = https://curl.se/bug/?i=19513 + [109] = https://curl.se/bug/?i=19727 + [110] = https://curl.se/bug/?i=19510 + [111] = https://curl.se/bug/?i=19509 + [112] = https://curl.se/bug/?i=19495 + [113] = https://curl.se/bug/?i=19653 + [114] = https://curl.se/bug/?i=19605 + [115] = https://curl.se/bug/?i=19855 + [116] = https://curl.se/bug/?i=19724 + [117] = https://curl.se/bug/?i=19644 + [118] = https://curl.se/bug/?i=19493 + [119] = https://curl.se/bug/?i=19483 + [120] = https://curl.se/bug/?i=19506 + [121] = https://curl.se/bug/?i=19606 + [122] = https://curl.se/bug/?i=19658 + [123] = https://curl.se/bug/?i=19602 + [124] = https://curl.se/bug/?i=19597 + [125] = https://curl.se/bug/?i=19651 + [126] = https://curl.se/bug/?i=19596 + [127] = https://curl.se/bug/?i=19594 + [128] = https://curl.se/bug/?i=19650 + [129] = https://curl.se/bug/?i=19649 + [130] = https://curl.se/bug/?i=19593 + [131] = https://curl.se/bug/?i=19591 + [132] = https://curl.se/bug/?i=19590 + [133] = https://curl.se/bug/?i=19471 + [134] = https://curl.se/bug/?i=19583 + [135] = https://curl.se/bug/?i=19796 + [136] = https://curl.se/bug/?i=19586 + [137] = https://curl.se/bug/?i=19578 + [138] = https://curl.se/bug/?i=19580 + [139] = https://curl.se/bug/?i=19579 + [140] = https://curl.se/bug/?i=19175 + [141] = https://curl.se/bug/?i=19854 + [142] = https://curl.se/bug/?i=19572 + [143] = https://curl.se/bug/?i=19581 + [144] = https://curl.se/bug/?i=19571 + [145] = https://curl.se/bug/?i=19794 + [146] = https://curl.se/bug/?i=19543 + [147] = https://curl.se/bug/?i=19568 + [148] = https://curl.se/bug/?i=19569 + [149] = https://curl.se/bug/?i=19567 + [150] = https://curl.se/bug/?i=19561 + [151] = https://curl.se/bug/?i=19560 + [152] = https://curl.se/bug/?i=19556 + [153] = https://curl.se/bug/?i=19564 + [154] = https://curl.se/bug/?i=19566 + [155] = https://curl.se/bug/?i=19788 + [156] = https://curl.se/bug/?i=19541 + [157] = https://curl.se/bug/?i=19520 + [158] = https://curl.se/bug/?i=19618 + [159] = https://curl.se/bug/?i=19540 + [160] = https://curl.se/bug/?i=19535 + [161] = https://curl.se/bug/?i=19640 + [162] = https://curl.se/bug/?i=19636 + [163] = https://curl.se/bug/?i=19637 + [164] = https://curl.se/bug/?i=19589 + [165] = https://curl.se/bug/?i=19790 + [166] = https://curl.se/bug/?i=19615 + [167] = https://curl.se/bug/?i=19609 + [168] = https://curl.se/bug/?i=19612 + [169] = https://curl.se/bug/?i=19748 + [170] = https://curl.se/bug/?i=19333 + [171] = https://curl.se/bug/?i=19714 + [172] = https://curl.se/bug/?i=19717 + [173] = https://curl.se/bug/?i=19789 + [174] = https://curl.se/bug/?i=19849 + [175] = https://curl.se/bug/?i=19784 + [176] = https://curl.se/bug/?i=19786 + [177] = https://curl.se/bug/?i=19462 + [178] = https://curl.se/bug/?i=19703 + [179] = https://curl.se/bug/?i=19705 + [180] = https://curl.se/bug/?i=19704 + [181] = https://curl.se/bug/?i=19702 + [182] = https://curl.se/bug/?i=19879 + [183] = https://curl.se/bug/?i=19701 + [184] = https://curl.se/bug/?i=19785 + [185] = https://curl.se/bug/?i=19781 + [186] = https://curl.se/bug/?i=19782 + [187] = https://curl.se/bug/?i=19164 + [188] = https://curl.se/bug/?i=19877 + [189] = https://curl.se/bug/?i=19604 + [190] = https://curl.se/bug/?i=19269 + [191] = https://curl.se/bug/?i=19663 + [192] = https://curl.se/bug/?i=19780 + [193] = https://curl.se/bug/?i=19779 + [194] = https://curl.se/bug/?i=19681 + [195] = https://curl.se/bug/?i=19692 + [196] = https://curl.se/bug/?i=19692 + [197] = https://curl.se/bug/?i=19687 + [198] = https://curl.se/bug/?i=19689 + [199] = https://curl.se/bug/?i=19688 + [200] = https://curl.se/bug/?i=19774 + [201] = https://curl.se/bug/?i=19775 + [202] = https://curl.se/bug/?i=19669 + [203] = https://curl.se/bug/?i=19683 + [204] = https://curl.se/bug/?i=19643 + [205] = https://curl.se/bug/?i=19838 + [206] = https://curl.se/bug/?i=19840 + [207] = https://curl.se/bug/?i=19844 + [208] = https://curl.se/bug/?i=19665 + [209] = https://curl.se/bug/?i=19384 + [210] = https://curl.se/bug/?i=19769 + [211] = https://curl.se/bug/?i=19768 + [212] = https://curl.se/bug/?i=19843 + [213] = https://curl.se/bug/?i=19842 + [214] = https://curl.se/bug/?i=19812 + [215] = https://curl.se/bug/?i=19764 + [216] = https://curl.se/bug/?i=18009 + [217] = https://curl.se/bug/?i=19763 + [219] = https://curl.se/bug/?i=19759 + [220] = https://curl.se/bug/?i=19756 + [221] = https://curl.se/bug/?i=19761 + [222] = https://curl.se/bug/?i=16973 + [223] = https://curl.se/bug/?i=16973 + [224] = https://curl.se/bug/?i=20031 + [225] = https://curl.se/bug/?i=19754 + [226] = https://curl.se/bug/?i=19751 + [227] = https://curl.se/bug/?i=20028 + [228] = https://curl.se/bug/?i=19836 + [229] = https://curl.se/bug/?i=19872 + [230] = https://curl.se/bug/?i=19745 + [231] = https://curl.se/bug/?i=19970 + [232] = https://curl.se/bug/?i=19746 + [233] = https://curl.se/bug/?i=19853 + [234] = https://curl.se/bug/?i=19870 + [235] = https://curl.se/bug/?i=19869 + [236] = https://curl.se/bug/?i=19830 + [237] = https://curl.se/bug/?i=19866 + [238] = https://curl.se/bug/?i=19786 + [239] = https://curl.se/bug/?i=19828 + [240] = https://curl.se/bug/?i=19829 + [241] = https://curl.se/bug/?i=19826 + [242] = https://curl.se/bug/?i=19734 + [243] = https://curl.se/bug/?i=19733 + [244] = https://curl.se/bug/?i=19732 + [245] = https://curl.se/bug/?i=19824 + [246] = https://curl.se/bug/?i=19823 + [247] = https://curl.se/bug/?i=19798 + [248] = https://curl.se/bug/?i=19811 + [249] = https://curl.se/bug/?i=19813 + [250] = https://curl.se/bug/?i=19933 + [251] = https://curl.se/bug/?i=19970 + [252] = https://curl.se/bug/?i=19809 + [253] = https://curl.se/bug/?i=19800 + [254] = https://curl.se/bug/?i=19808 + [255] = https://curl.se/bug/?i=19803 + [256] = https://curl.se/bug/?i=19864 + [257] = https://curl.se/bug/?i=19802 + [258] = https://curl.se/bug/?i=19864 + [259] = https://curl.se/bug/?i=19864 + [260] = https://curl.se/bug/?i=19863 + [261] = https://curl.se/bug/?i=19816 + [262] = https://curl.se/bug/?i=19862 + [263] = https://curl.se/bug/?i=19861 + [264] = https://curl.se/bug/?i=19860 + [265] = https://github.com/curl/curl/commit/ce06fe7771052549ff430c86173b2eaca91f8a9c#r172215567 + [266] = https://curl.se/bug/?i=19857 + [267] = https://curl.se/bug/?i=19858 + [268] = https://curl.se/bug/?i=19753 + [269] = https://curl.se/bug/?i=19965 + [272] = https://curl.se/bug/?i=20026 + [274] = https://curl.se/bug/?i=19964 + [275] = https://curl.se/bug/?i=18189 + [276] = https://curl.se/bug/?i=19922 + [277] = https://curl.se/bug/?i=19949 + [278] = https://curl.se/bug/?i=19920 + [279] = https://curl.se/bug/?i=19918 + [280] = https://curl.se/bug/?i=19770 + [282] = https://curl.se/bug/?i=19960 + [283] = https://curl.se/bug/?i=19915 + [285] = https://curl.se/bug/?i=19911 + [286] = https://curl.se/bug/?i=19900 + [288] = https://curl.se/bug/?i=19907 + [291] = https://curl.se/bug/?i=19902 + [292] = https://curl.se/bug/?i=19888 + [294] = https://curl.se/bug/?i=19901 + [295] = https://curl.se/bug/?i=19899 + [297] = https://curl.se/bug/?i=19894 + [298] = https://curl.se/bug/?i=19740 + [299] = https://curl.se/bug/?i=19945 + [301] = https://curl.se/bug/?i=19896 + [302] = https://curl.se/bug/?i=19942 + [303] = https://curl.se/bug/?i=19934 + [304] = https://curl.se/bug/?i=19944 + [305] = https://curl.se/bug/?i=19891 + [306] = https://curl.se/bug/?i=20010 + [307] = https://curl.se/bug/?i=19875 + [308] = https://curl.se/bug/?i=19887 + [309] = https://curl.se/bug/?i=19886 + [310] = https://curl.se/bug/?i=20012 + [311] = https://curl.se/bug/?i=19938 + [312] = https://curl.se/bug/?i=20011 + [313] = https://curl.se/bug/?i=20009 + [314] = https://curl.se/bug/?i=20008 + [316] = https://curl.se/bug/?i=19997 + [318] = https://curl.se/bug/?i=20002 + [319] = https://curl.se/bug/?i=19995 + [320] = https://curl.se/bug/?i=20001 + [321] = https://curl.se/bug/?i=20000 + [322] = https://curl.se/bug/?i=19966 + [323] = https://curl.se/bug/?i=19999 + [324] = https://curl.se/bug/?i=19980 + [325] = https://curl.se/bug/?i=19957 + [329] = https://curl.se/bug/?i=19996 + [330] = https://curl.se/bug/?i=19992 + [334] = https://curl.se/bug/?i=19984 + [335] = https://curl.se/bug/?i=19986 + [336] = https://curl.se/bug/?i=19978 diff --git a/REUSE.toml b/REUSE.toml index 40531913af3b..e341973ad3d3 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -13,16 +13,11 @@ SPDX-PackageDownloadLocation = "https://curl.se/" [[annotations]] path = [ - ".mailmap", - "docs/FAQ", "docs/INSTALL", - "docs/KNOWN_BUGS", "docs/libcurl/symbols-in-versions", "docs/MAIL-ETIQUETTE", "docs/options-in-versions", "docs/THANKS", - "docs/TODO", - "GIT-INFO.md", "lib/libcurl.vers.in", "lib/libcurl.def", "packages/OS400/README.OS400", @@ -37,6 +32,7 @@ path = [ "RELEASE-NOTES", "renovate.json", "tests/certs/**", + "tests/data/data**", "tests/data/test**", "tests/valgrind.supp", ] diff --git a/acinclude.m4 b/acinclude.m4 index 517de0c4a63e..775102033cdb 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -190,7 +190,7 @@ AC_DEFUN([CURL_CHECK_NATIVE_WINDOWS], [ curl_cv_native_windows="no" ]) ]) - AM_CONDITIONAL(DOING_NATIVE_WINDOWS, test "x$curl_cv_native_windows" = xyes) + AM_CONDITIONAL(DOING_NATIVE_WINDOWS, test "$curl_cv_native_windows" = "yes") ]) @@ -769,7 +769,7 @@ AC_DEFUN([CURL_CHECK_STRUCT_TIMEVAL], [ #include ]],[[ struct timeval ts; - ts.tv_sec = 0; + ts.tv_sec = 0; ts.tv_usec = 0; (void)ts; ]]) @@ -820,7 +820,7 @@ AC_DEFUN([CURL_CHECK_FUNC_CLOCK_GETTIME_MONOTONIC], [ ]) dnl Definition of HAVE_CLOCK_GETTIME_MONOTONIC is intentionally postponed - dnl until library linking and run-time checks for clock_gettime succeed. + dnl until library linking and runtime checks for clock_gettime succeed. ]) dnl CURL_CHECK_FUNC_CLOCK_GETTIME_MONOTONIC_RAW @@ -910,7 +910,7 @@ AC_DEFUN([CURL_CHECK_LIBS_CLOCK_GETTIME_MONOTONIC], [ curl_func_clock_gettime="yes" ;; *) - if test "x$dontwant_rt" = "xyes" ; then + if test "$dontwant_rt" = "yes"; then AC_MSG_WARN([needs -lrt but asked not to use it, HAVE_CLOCK_GETTIME_MONOTONIC will not be defined]) curl_func_clock_gettime="no" else @@ -926,7 +926,7 @@ AC_DEFUN([CURL_CHECK_LIBS_CLOCK_GETTIME_MONOTONIC], [ esac # dnl only do runtime verification when not cross-compiling - if test "x$cross_compiling" != "xyes" && + if test "$cross_compiling" != "yes" && test "$curl_func_clock_gettime" = "yes"; then AC_MSG_CHECKING([if monotonic clock_gettime works]) CURL_RUN_IFELSE([ @@ -1082,11 +1082,11 @@ dnl macro. It must also run AFTER all lib-checking macros are complete. AC_DEFUN([CURL_VERIFY_RUNTIMELIBS], [ dnl this test is of course not sensible if we are cross-compiling! - if test "x$cross_compiling" != xyes; then + if test "$cross_compiling" != "yes"; then dnl just run a program to verify that the libs checked for previous to this - dnl point also is available run-time! - AC_MSG_CHECKING([run-time libs availability]) + dnl point also is available runtime! + AC_MSG_CHECKING([runtime libs availability]) CURL_RUN_IFELSE([ int main(void) { @@ -1095,7 +1095,7 @@ AC_DEFUN([CURL_VERIFY_RUNTIMELIBS], [ ], AC_MSG_RESULT([fine]), AC_MSG_RESULT([failed]) - AC_MSG_ERROR([one or more libs available at link-time are not available run-time. Libs used at link-time: $LIBS]) + AC_MSG_ERROR([one or more libs available at link-time are not available runtime. Libs used at link-time: $LIBS]) ) dnl if this test fails, configure has already stopped @@ -1122,7 +1122,7 @@ AC_DEFUN([CURL_CHECK_CA_BUNDLE], [ AC_ARG_WITH(ca-bundle, AS_HELP_STRING([--with-ca-bundle=FILE], [Absolute path to a file containing CA certificates (example: /etc/ca-bundle.crt)]) -AS_HELP_STRING([--without-ca-bundle], [Don't use a default CA bundle]), +AS_HELP_STRING([--without-ca-bundle], [Do not use a default CA bundle]), [ want_ca="$withval" if test "x$want_ca" = "xyes"; then @@ -1136,7 +1136,7 @@ AS_HELP_STRING([--with-ca-path=DIRECTORY], their filenames in a hash format. This option can be used with the OpenSSL, \ GnuTLS, mbedTLS and wolfSSL backends. Refer to OpenSSL c_rehash for details. \ (example: /etc/certificates)]) -AS_HELP_STRING([--without-ca-path], [Don't use a default CA path]), +AS_HELP_STRING([--without-ca-path], [Do not use a default CA path]), [ want_capath="$withval" if test "x$want_capath" = "xyes"; then @@ -1149,26 +1149,26 @@ AS_HELP_STRING([--without-ca-path], [Don't use a default CA path]), capath_warning=" (warning: certs not found)" check_capath="" - if test "x$APPLE_SECTRUST_ENABLED" = "x1"; then + if test "$APPLE_SECTRUST_ENABLED" = "1"; then ca_native="Apple SecTrust" else ca_native="no" fi - if test "x$want_ca" != "xno" -a "x$want_ca" != "xunset" -a \ - "x$want_capath" != "xno" -a "x$want_capath" != "xunset"; then + if test "x$want_ca" != "xno" && test "x$want_ca" != "xunset" && + test "x$want_capath" != "xno" && test "x$want_capath" != "xunset"; then dnl both given ca="$want_ca" capath="$want_capath" - elif test "x$want_ca" != "xno" -a "x$want_ca" != "xunset"; then + elif test "x$want_ca" != "xno" && test "x$want_ca" != "xunset"; then dnl --with-ca-bundle given ca="$want_ca" capath="no" - elif test "x$want_capath" != "xno" -a "x$want_capath" != "xunset"; then + elif test "x$want_capath" != "xno" && test "x$want_capath" != "xunset"; then dnl --with-ca-path given capath="$want_capath" ca="no" - elif test "x$ca_native" != "xno"; then + elif test "$ca_native" != "no"; then # native ca configured, do not look further ca="no" capath="no" @@ -1177,15 +1177,15 @@ AS_HELP_STRING([--without-ca-path], [Don't use a default CA path]), dnl Both auto-detections can be skipped by --without-ca-* ca="no" capath="no" - if test "x$cross_compiling" != "xyes" -a \ - "x$curl_cv_native_windows" != "xyes"; then + if test "$cross_compiling" != "yes" && + test "$curl_cv_native_windows" != "yes"; then dnl NOT cross-compiling and... dnl neither of the --with-ca-* options are provided if test "x$want_ca" = "xunset"; then dnl the path we previously would have installed the curl CA bundle dnl to, and thus we now check for an already existing cert in that dnl place in case we find no other - if test "x$prefix" != xNONE; then + if test "x$prefix" != "xNONE"; then cac="${prefix}/share/curl/curl-ca-bundle.crt" else cac="$ac_default_prefix/share/curl/curl-ca-bundle.crt" @@ -1221,7 +1221,7 @@ AS_HELP_STRING([--without-ca-path], [Don't use a default CA path]), check_capath="$capath" fi - if test ! -z "$check_capath"; then + if test -n "$check_capath"; then for a in "$check_capath"; do if test -d "$a" && ls "$a"/[[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]].0 >/dev/null 2>/dev/null; then if test "x$capath" = "xno"; then @@ -1255,16 +1255,16 @@ AS_HELP_STRING([--without-ca-path], [Don't use a default CA path]), AC_MSG_CHECKING([whether to use OpenSSL's built-in CA store]) AC_ARG_WITH(ca-fallback, AS_HELP_STRING([--with-ca-fallback], [Use OpenSSL's built-in CA store]) -AS_HELP_STRING([--without-ca-fallback], [Don't use OpenSSL's built-in CA store]), +AS_HELP_STRING([--without-ca-fallback], [Do not use OpenSSL's built-in CA store]), [ - if test "x$with_ca_fallback" != "xyes" -a "x$with_ca_fallback" != "xno"; then + if test "x$with_ca_fallback" != "xyes" && test "x$with_ca_fallback" != "xno"; then AC_MSG_ERROR([--with-ca-fallback only allows yes or no as parameter]) fi ], [ with_ca_fallback="no"]) AC_MSG_RESULT([$with_ca_fallback]) if test "x$with_ca_fallback" = "xyes"; then - if test "x$OPENSSL_ENABLED" != "x1"; then + if test "$OPENSSL_ENABLED" != "1"; then AC_MSG_ERROR([--with-ca-fallback only works with OpenSSL]) fi AC_DEFINE_UNQUOTED(CURL_CA_FALLBACK, 1, [define "1" to use OpenSSL's built-in CA store]) @@ -1283,7 +1283,7 @@ AC_DEFUN([CURL_CHECK_CA_EMBED], [ AC_ARG_WITH(ca-embed, AS_HELP_STRING([--with-ca-embed=FILE], [Absolute path to a file containing CA certificates to embed in the curl tool (example: /etc/ca-bundle.crt)]) -AS_HELP_STRING([--without-ca-embed], [Don't embed a default CA bundle in the curl tool]), +AS_HELP_STRING([--without-ca-embed], [Do not embed a default CA bundle in the curl tool]), [ want_ca_embed="$withval" if test "x$want_ca_embed" = "xyes"; then @@ -1293,7 +1293,7 @@ AS_HELP_STRING([--without-ca-embed], [Don't embed a default CA bundle in the cur [ want_ca_embed="unset" ]) CURL_CA_EMBED='' - if test "x$want_ca_embed" != "xno" -a "x$want_ca_embed" != "xunset" -a -f "$want_ca_embed"; then + if test "x$want_ca_embed" != "xno" && test "x$want_ca_embed" != "xunset" && test -f "$want_ca_embed"; then if test -n "$PERL"; then CURL_CA_EMBED="$want_ca_embed" AC_SUBST(CURL_CA_EMBED) @@ -1307,38 +1307,6 @@ AS_HELP_STRING([--without-ca-embed], [Don't embed a default CA bundle in the cur fi ]) -dnl CURL_CHECK_WIN32_LARGEFILE -dnl ------------------------------------------------- -dnl Check if curl's Win32 large file will be used - -AC_DEFUN([CURL_CHECK_WIN32_LARGEFILE], [ - AC_REQUIRE([CURL_CHECK_NATIVE_WINDOWS])dnl - if test "$curl_cv_native_windows" = 'yes'; then - AC_MSG_CHECKING([whether build target supports Win32 large files]) - if test "$curl_cv_wince" = 'yes'; then - dnl Windows CE does not support large files - curl_win32_has_largefile='no' - else - dnl All mingw-w64 versions support large files - curl_win32_has_largefile='yes' - fi - case "$curl_win32_has_largefile" in - yes) - if test x"$enable_largefile" = 'xno'; then - AC_MSG_RESULT([yes (large file disabled)]) - else - AC_MSG_RESULT([yes (large file enabled)]) - AC_DEFINE_UNQUOTED(USE_WIN32_LARGE_FILES, 1, - [Define to 1 if you are building a Windows target with large file support.]) - fi - ;; - *) - AC_MSG_RESULT([no]) - ;; - esac - fi -]) - dnl CURL_CHECK_WIN32_CRYPTO dnl ------------------------------------------------- dnl Check if curl's Win32 crypto lib can be used @@ -1347,7 +1315,7 @@ AC_DEFUN([CURL_CHECK_WIN32_CRYPTO], [ 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_native_windows" = "yes" -a "$curl_cv_winuwp" != "yes"; then + if test "$curl_cv_native_windows" = "yes" && test "$curl_cv_winuwp" != "yes"; then AC_COMPILE_IFELSE([ AC_LANG_PROGRAM([[ #undef inline @@ -1414,7 +1382,7 @@ AC_DEFUN([CURL_CHECK_PKGCONFIG], [ [$PATH:/usr/bin:/usr/local/bin]) fi - if test "x$PKGCONFIG" != "xno"; then + if test "$PKGCONFIG" != "no"; then AC_MSG_CHECKING([for $1 options with pkg-config]) dnl ask pkg-config about $1 itexists=`CURL_EXPORT_PCDIR([$2]) dnl @@ -1455,7 +1423,7 @@ dnl Save build info for test runner to pick up and log AC_DEFUN([CURL_PREPARE_BUILDINFO], [ curl_pflags="" - if test "$curl_cv_apple" = 'yes'; then + if test "$curl_cv_apple" = "yes"; then curl_pflags="${curl_pflags} APPLE" fi case $host in @@ -1475,23 +1443,20 @@ AC_DEFUN([CURL_PREPARE_BUILDINFO], [ fi ;; esac - if test "$curl_cv_native_windows" = 'yes'; then + if test "$curl_cv_native_windows" = "yes"; then curl_pflags="${curl_pflags} WIN32" fi - if test "$curl_cv_wince" = 'yes'; then - curl_pflags="${curl_pflags} WINCE" - fi - if test "$curl_cv_winuwp" = 'yes'; then + if test "$curl_cv_winuwp" = "yes"; then curl_pflags="${curl_pflags} UWP" fi - if test "$curl_cv_cygwin" = 'yes'; then + if test "$curl_cv_cygwin" = "yes"; then curl_pflags="${curl_pflags} CYGWIN" fi case $host_os in msdos*) curl_pflags="${curl_pflags} DOS";; amiga*) curl_pflags="${curl_pflags} AMIGA";; esac - if test "x$compiler_id" = 'xGNU_C'; then + if test "$compiler_id" = "GNU_C"; then curl_pflags="${curl_pflags} GCC" fi if test "$compiler_id" = "APPLECLANG"; then @@ -1502,7 +1467,7 @@ AC_DEFUN([CURL_PREPARE_BUILDINFO], [ case $host_os in mingw*) curl_pflags="${curl_pflags} MINGW";; esac - if test "x$cross_compiling" = 'xyes'; then + if test "$cross_compiling" = "yes"; then curl_pflags="${curl_pflags} CROSS" fi squeeze curl_pflags @@ -1544,7 +1509,7 @@ TEST EINVAL TEST AC_MSG_RESULT([$cpp]) dnl we need cpp -P so check if it works then - if test "x$cpp" = "xyes"; then + if test "$cpp" = "yes"; then AC_MSG_CHECKING([if cpp -P works]) OLDCPPFLAGS=$CPPFLAGS CPPFLAGS="$CPPFLAGS -P" @@ -1554,7 +1519,7 @@ TEST EINVAL TEST ], [cpp_p=yes], [cpp_p=no]) AC_MSG_RESULT([$cpp_p]) - if test "x$cpp_p" = "xno"; then + if test "$cpp_p" = "no"; then AC_MSG_WARN([failed to figure out cpp -P alternative]) # without -P CPPPFLAG="" @@ -1574,7 +1539,7 @@ TEST EINVAL TEST dnl CURL_DARWIN_CFLAGS dnl dnl Set -Werror=partial-availability to detect possible breaking code -dnl with very low deployment targets. +dnl with low deployment targets. dnl AC_DEFUN([CURL_DARWIN_CFLAGS], [ @@ -1591,7 +1556,7 @@ AC_DEFUN([CURL_DARWIN_CFLAGS], [ dnl CURL_SUPPORTS_BUILTIN_AVAILABLE dnl dnl Check to see if the compiler supports __builtin_available. This built-in -dnl compiler function first appeared in Apple LLVM 9.0.0. It's so new that, at +dnl compiler function first appeared in Apple LLVM 9.0.0. It is so new that, at dnl the time this macro was written, the function was not yet documented. Its dnl purpose is to return true if the code is running under a certain OS version dnl or later. diff --git a/appveyor.sh b/appveyor.sh index 4be76095ee4a..bfcc2b9e5a72 100644 --- a/appveyor.sh +++ b/appveyor.sh @@ -35,14 +35,30 @@ esac if [ "${APPVEYOR_BUILD_WORKER_IMAGE}" = 'Visual Studio 2022' ]; then openssl_root_win="C:/OpenSSL-v35${openssl_suffix}" + openssl_root="$(cygpath "${openssl_root_win}")" elif [ "${APPVEYOR_BUILD_WORKER_IMAGE}" = 'Visual Studio 2019' ]; then openssl_root_win="C:/OpenSSL-v30${openssl_suffix}" -else - openssl_root_win="C:/OpenSSL-v111${openssl_suffix}" + openssl_root="$(cygpath "${openssl_root_win}")" fi -openssl_root="$(cygpath "${openssl_root_win}")" if [ "${BUILD_SYSTEM}" = 'CMake' ]; then + # Install custom cmake version + if [ -n "${CMAKE_VERSION:-}" ]; then + cmake_ver=$(printf '%02d%02d' \ + "$(echo "${CMAKE_VERSION}" | cut -f1 -d.)" \ + "$(echo "${CMAKE_VERSION}" | cut -f2 -d.)") + if [ "${cmake_ver}" -ge '0320' ]; then + fn="cmake-${CMAKE_VERSION}-windows-x86_64" + else + fn="cmake-${CMAKE_VERSION}-win64-x64" + fi + curl --disable --fail --silent --show-error --connect-timeout 15 --max-time 60 --retry 3 --retry-connrefused \ + --location "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/${fn}.zip" --output bin.zip + 7z x -y bin.zip >/dev/null + rm -f bin.zip + PATH="$PWD/${fn}/bin:$PATH" + fi + # Set env CHKPREFILL to the value '_chkprefill' to compare feature detection # results with and without the pre-fill feature. They have to match. for _chkprefill in '' ${CHKPREFILL:-}; do @@ -76,7 +92,7 @@ if [ "${BUILD_SYSTEM}" = 'CMake' ]; then -DCURL_USE_OPENSSL="${OPENSSL}" \ -DCURL_USE_LIBPSL=OFF \ ${options} \ - || { cat ${root}/_bld/CMakeFiles/CMake* 2>/dev/null; false; } + || { cat "${root}"/_bld/CMakeFiles/CMake* 2>/dev/null; false; } [ "${APPVEYOR_BUILD_WORKER_IMAGE}" = 'Visual Studio 2013' ] && cd .. done if [ -d _bld_chkprefill ] && ! diff -u _bld/lib/curl_config.h _bld_chkprefill/lib/curl_config.h; then @@ -93,12 +109,14 @@ elif [ "${BUILD_SYSTEM}" = 'VisualStudioSolution' ]; then ( cd projects ./generate.bat "${VC_VERSION}" - msbuild.exe -maxcpucount "-property:Configuration=${PRJ_CFG}" "Windows/${VC_VERSION}/curl-all.sln" + msbuild.exe -maxcpucount "-property:Configuration=${PRJ_CFG}" "-property:Platform=${PLAT}" "Windows/${VC_VERSION}/curl-all.sln" ) - curl="build/Win32/${VC_VERSION}/${PRJ_CFG}/curld.exe" + [ "${PLAT}" = 'x64' ] && platdir='Win64' || platdir='Win32' + [[ "${PRJ_CFG}" = *'Debug'* ]] && binsuffix='d' || binsuffix='' + curl="build/${platdir}/${VC_VERSION}/${PRJ_CFG}/curl${binsuffix}.exe" fi -find . \( -name '*.exe' -o -name '*.dll' -o -name '*.lib' -o -name '*.pdb' \) -exec file '{}' \; +find . \( -name '*.exe' -o -name '*.dll' -o -name '*.lib' -o -name '*.pdb' \) -exec file -- '{}' \; if [ -z "${SKIP_RUN:-}" ]; then "${curl}" --disable --version else diff --git a/appveyor.yml b/appveyor.yml index af6ecd2c159b..91a425c7faca 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -46,14 +46,14 @@ environment: # generated CMake-based Visual Studio builds - - job_name: 'CMake, VS2022, Release, x64, OpenSSL 3.5, Shared, Build-tests' + - job_name: 'CM VS2022, Release, x64, OpenSSL 3.5, Shared, Build-tests' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022' PRJ_GEN: 'Visual Studio 17 2022' TARGET: '-A x64' PRJ_CFG: Release OPENSSL: 'ON' SHARED: 'ON' - - job_name: 'CMake, VS2022, Release, arm64, Schannel, Static, Build-tests' + - job_name: 'CM VS2022, Release, arm64, Schannel, Static, Build-tests' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022' PRJ_GEN: 'Visual Studio 17 2022' TARGET: '-A ARM64' @@ -61,7 +61,7 @@ environment: SCHANNEL: 'ON' DEBUG: 'OFF' CURLDEBUG: 'ON' - - job_name: 'CMake, VS2010, Debug, x64, Schannel, Shared, Build-tests & examples, XP' + - job_name: 'CM VS2010, Debug, x64, Schannel, Shared, Build-tests & examples, XP' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2013' PRJ_GEN: 'Visual Studio 10 2010' TARGET: '-A x64' @@ -70,38 +70,40 @@ environment: SCHANNEL: 'ON' SHARED: 'ON' EXAMPLES: 'ON' - - job_name: 'CMake, VS2012, Release, x86, OpenSSL 1.1.1 + Schannel, Shared, Build-tests' + - job_name: 'CM VS2012, Release, x86, Schannel, Shared, Build-tests' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015' PRJ_GEN: 'Visual Studio 11 2012' TARGET: '-A Win32' PRJ_CFG: Release - OPENSSL: 'ON' SCHANNEL: 'ON' SHARED: 'ON' - - job_name: 'CMake, VS2013, Debug, x64, OpenSSL 1.1.1, Shared, Build-only' + - job_name: 'CM VS2013, Debug, x64, Schannel, Shared, Build-only' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015' + CMAKE_VERSION: '3.18.4' PRJ_GEN: 'Visual Studio 12 2013' TARGET: '-A x64' PRJ_CFG: Debug - OPENSSL: 'ON' + SCHANNEL: 'ON' SHARED: 'ON' TFLAGS: 'skipall' - - job_name: 'CMake, VS2015, Debug, x64, OpenSSL 1.1.1, Static, Build-only' + - job_name: 'CM VS2015, Debug, x64, Schannel, Static, Build-only' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015' + CMAKE_VERSION: '3.19.8' PRJ_GEN: 'Visual Studio 14 2015' TARGET: '-A x64' PRJ_CFG: Debug - OPENSSL: 'ON' + SCHANNEL: 'ON' TFLAGS: 'skipall' - - job_name: 'CMake, VS2017, Debug, x64, OpenSSL 1.1.1, Shared, Build-only' + - job_name: 'CM VS2017, Debug, x64, Schannel, Shared, Build-only' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2017' + CMAKE_VERSION: '3.20.6' PRJ_GEN: 'Visual Studio 15 2017' TARGET: '-A x64' PRJ_CFG: Debug - OPENSSL: 'ON' + SCHANNEL: 'ON' SHARED: 'ON' TFLAGS: 'skipall' - - job_name: 'CMake, VS2019, Debug, x64, OpenSSL 3.0 + Schannel, Shared, Build-tests' + - job_name: 'CM VS2019, Debug, x64, OpenSSL 3.0 + Schannel, Shared, Build-tests' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2019' PRJ_GEN: 'Visual Studio 16 2019' TARGET: '-A x64' @@ -109,7 +111,7 @@ environment: OPENSSL: 'ON' SCHANNEL: 'ON' SHARED: 'ON' - - job_name: 'CMake, VS2022, Debug, x64, OpenSSL 3.5 + Schannel, Static, Unicode, Build-tests & examples, clang-cl' + - job_name: 'CM VS2022, Debug, x64, OpenSSL 3.5 + Schannel, Static, Unicode, Build-tests & examples, clang-cl' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022' PRJ_GEN: 'Visual Studio 17 2022' TARGET: '-A x64' @@ -119,14 +121,14 @@ environment: ENABLE_UNICODE: 'ON' EXAMPLES: 'ON' TOOLSET: 'ClangCl' - - job_name: 'CMake, VS2022, Debug, x64, Schannel, Static, Unicode, Build-tests' + - job_name: 'CM VS2022, Debug, x64, Schannel, Static, Unicode, Build-tests' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022' PRJ_GEN: 'Visual Studio 17 2022' TARGET: '-A x64' PRJ_CFG: Debug SCHANNEL: 'ON' ENABLE_UNICODE: 'ON' - - job_name: 'CMake, VS2022, Release, x64, Schannel, Shared, Unicode, DEBUGBUILD, no-CURLDEBUG, Build-tests' + - job_name: 'CM VS2022, Release, x64, Schannel, Shared, Unicode, DEBUGBUILD, no-CURLDEBUG, Build-tests' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022' PRJ_GEN: 'Visual Studio 17 2022' TARGET: '-A x64' @@ -135,12 +137,12 @@ environment: ENABLE_UNICODE: 'ON' SHARED: 'ON' CURLDEBUG: 'OFF' - - job_name: 'CMake, VS2022, Debug, x64, no SSL, Static, Build-tests' + - job_name: 'CM VS2022, Debug, x64, no SSL, Static, Build-tests' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022' PRJ_GEN: 'Visual Studio 17 2022' TARGET: '-A x64' PRJ_CFG: Debug - - job_name: 'CMake, VS2022, Debug, x64, no SSL, Static, HTTP only, Build-tests' + - job_name: 'CM VS2022, Debug, x64, no SSL, Static, HTTP only, Build-tests' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2022' PRJ_GEN: 'Visual Studio 17 2022' TARGET: '-A x64' @@ -149,10 +151,17 @@ environment: # generated VisualStudioSolution-based builds - - job_name: 'VisualStudioSolution, VS2013, Debug, x86, Schannel, Build-only' + - job_name: 'VisualStudioSolution VS2010, Release, x86, Schannel, Build-only' + APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2013' + BUILD_SYSTEM: VisualStudioSolution + PRJ_CFG: 'DLL Release - DLL Windows SSPI - DLL WinIDN' + PLAT: 'Win32' + VC_VERSION: VC10 + - job_name: 'VisualStudioSolution VS2013, Debug, x64, Schannel, Build-only' APPVEYOR_BUILD_WORKER_IMAGE: 'Visual Studio 2015' BUILD_SYSTEM: VisualStudioSolution PRJ_CFG: 'DLL Debug - DLL Windows SSPI - DLL WinIDN' + PLAT: 'x64' VC_VERSION: VC12 install: diff --git a/configure.ac b/configure.ac index 999ab122a323..270015832634 100644 --- a/configure.ac +++ b/configure.ac @@ -25,11 +25,10 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ(2.59) -dnl We don't know the version number "statically" so we use a dash here +dnl We do not know the version number "statically" so we use a dash here AC_INIT([curl], [-], [a suitable curl mailing list: https://curl.se/mail/]) XC_OVR_ZZ50 -XC_OVR_ZZ60 CURL_OVERRIDE_AUTOCONF dnl configure script copyright @@ -45,12 +44,12 @@ AM_MAINTAINER_MODE m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) CURL_CHECK_OPTION_DEBUG -AM_CONDITIONAL(DEBUGBUILD, test x$want_debug = xyes) +AM_CONDITIONAL(DEBUGBUILD, test "$want_debug" = "yes") CURL_CHECK_OPTION_OPTIMIZE CURL_CHECK_OPTION_WARNINGS CURL_CHECK_OPTION_WERROR CURL_CHECK_OPTION_CURLDEBUG -AM_CONDITIONAL(CURLDEBUG, test x$want_curldebug = xyes) +AM_CONDITIONAL(CURLDEBUG, test "$want_curldebug" = "yes") CURL_CHECK_OPTION_SYMBOL_HIDING CURL_CHECK_OPTION_ARES CURL_CHECK_OPTION_RT @@ -141,36 +140,37 @@ AC_SUBST(VERSIONNUM) dnl dnl initialize all the info variables - curl_ssl_msg="no (--with-{openssl,gnutls,mbedtls,wolfssl,schannel,amissl,rustls} )" - curl_ssh_msg="no (--with-{libssh,libssh2})" - curl_zlib_msg="no (--with-zlib)" - curl_brotli_msg="no (--with-brotli)" - curl_zstd_msg="no (--with-zstd)" - curl_gss_msg="no (--with-gssapi)" - curl_gsasl_msg="no (--with-gsasl)" -curl_tls_srp_msg="no (--enable-tls-srp)" - curl_res_msg="blocking (--enable-ares / --enable-threaded-resolver)" - curl_ipv6_msg="no (--enable-ipv6)" -curl_unix_sockets_msg="no (--enable-unix-sockets)" - curl_idn_msg="no (--with-{libidn2,winidn})" - curl_docs_msg="enabled (--disable-docs)" - curl_manual_msg="no (--enable-manual)" -curl_libcurl_msg="enabled (--disable-libcurl-option)" -curl_verbose_msg="enabled (--disable-verbose)" - curl_sspi_msg="no (--enable-sspi)" - curl_ldap_msg="no (--enable-ldap / --with-ldap-lib / --with-lber-lib)" - curl_ldaps_msg="no (--enable-ldaps)" - curl_ipfs_msg="no (--enable-ipfs)" - curl_rtsp_msg="no (--enable-rtsp)" - curl_rtmp_msg="no (--with-librtmp)" - curl_psl_msg="no (--with-libpsl)" - curl_altsvc_msg="enabled (--disable-alt-svc)" -curl_headers_msg="enabled (--disable-headers-api)" - curl_hsts_msg="enabled (--disable-hsts)" - ssl_backends= - curl_h1_msg="enabled (internal)" - curl_h2_msg="no (--with-nghttp2)" - curl_h3_msg="no (--with-ngtcp2 --with-nghttp3, --with-quiche, --with-openssl-quic)" + curl_ssl_msg="no (--with-{openssl,gnutls,mbedtls,wolfssl,schannel,amissl,rustls} )" + curl_ssh_msg="no (--with-{libssh,libssh2})" + curl_zlib_msg="no (--with-zlib)" + curl_brotli_msg="no (--with-brotli)" + curl_zstd_msg="no (--with-zstd)" + curl_gss_msg="no (--with-gssapi)" + curl_gsasl_msg="no (--with-gsasl)" + curl_tls_srp_msg="no (--enable-tls-srp)" + curl_res_msg="blocking (--enable-ares / --enable-threaded-resolver)" + curl_ipv6_msg="no (--enable-ipv6)" +curl_unix_sockets_msg="no (--enable-unix-sockets)" + curl_idn_msg="no (--with-{libidn2,winidn})" + curl_docs_msg="enabled (--disable-docs)" + curl_manual_msg="no (--enable-manual)" + curl_libcurl_msg="enabled (--disable-libcurl-option)" + curl_typecheck_msg="enabled (--disable-typecheck)" + curl_verbose_msg="enabled (--disable-verbose)" + curl_sspi_msg="no (--enable-sspi)" + curl_ldap_msg="no (--enable-ldap / --with-ldap-lib / --with-lber-lib)" + curl_ldaps_msg="no (--enable-ldaps)" + curl_ipfs_msg="no (--enable-ipfs)" + curl_rtsp_msg="no (--enable-rtsp)" + curl_rtmp_msg="no (--with-librtmp)" + curl_psl_msg="no (--with-libpsl)" + curl_altsvc_msg="enabled (--disable-alt-svc)" + curl_headers_msg="enabled (--disable-headers-api)" + curl_hsts_msg="enabled (--disable-hsts)" + ssl_backends= + curl_h1_msg="enabled (internal)" + curl_h2_msg="no (--with-nghttp2)" + curl_h3_msg="no (--with-ngtcp2 --with-nghttp3, --with-quiche, --with-openssl-quic)" enable_altsvc="yes" hsts="yes" @@ -225,7 +225,7 @@ AS_HELP_STRING([--with-ssl=PATH],[old version of --with-openssl]) AS_HELP_STRING([--without-ssl], [build without any TLS library]),[ OPT_SSL=$withval OPT_OPENSSL=$withval - if test X"$withval" != Xno; then + if test "x$withval" != "xno"; then TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }OpenSSL" else SSL_DISABLED="D" @@ -235,7 +235,7 @@ AS_HELP_STRING([--without-ssl], [build without any TLS library]),[ AC_ARG_WITH(openssl,dnl AS_HELP_STRING([--with-openssl=PATH],[Where to look for OpenSSL, PATH points to the SSL installation (default: /usr/local/ssl); when possible, set the PKG_CONFIG_PATH environment variable instead of using this option]),[ OPT_OPENSSL=$withval - if test X"$withval" != Xno; then + if test "x$withval" != "xno"; then TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }OpenSSL" fi ]) @@ -244,7 +244,7 @@ OPT_GNUTLS=no AC_ARG_WITH(gnutls,dnl AS_HELP_STRING([--with-gnutls=PATH],[where to look for GnuTLS, PATH points to the installation root]),[ OPT_GNUTLS=$withval - if test X"$withval" != Xno; then + if test "x$withval" != "xno"; then TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }GnuTLS" fi ]) @@ -253,7 +253,7 @@ OPT_MBEDTLS=no AC_ARG_WITH(mbedtls,dnl AS_HELP_STRING([--with-mbedtls=PATH],[where to look for mbedTLS, PATH points to the installation root]),[ OPT_MBEDTLS=$withval - if test X"$withval" != Xno; then + if test "x$withval" != "xno"; then TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }mbedTLS" fi ]) @@ -262,7 +262,7 @@ OPT_WOLFSSL=no AC_ARG_WITH(wolfssl,dnl AS_HELP_STRING([--with-wolfssl=PATH],[where to look for wolfSSL, PATH points to the installation root (default: system lib default)]),[ OPT_WOLFSSL=$withval - if test X"$withval" != Xno; then + if test "x$withval" != "xno"; then TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }wolfSSL" fi ]) @@ -271,7 +271,7 @@ OPT_RUSTLS=no AC_ARG_WITH(rustls,dnl AS_HELP_STRING([--with-rustls=PATH],[where to look for Rustls, PATH points to the installation root]),[ OPT_RUSTLS=$withval - if test X"$withval" != Xno; then + if test "x$withval" != "xno"; then TLSCHOICE="${TLSCHOICE:+$TLSCHOICE, }Rustls" experimental="$experimental Rustls" fi @@ -291,7 +291,7 @@ TEST_NGHTTPX=nghttpx AC_ARG_WITH(test-nghttpx,dnl AS_HELP_STRING([--with-test-nghttpx=PATH],[where to find nghttpx for testing]), TEST_NGHTTPX=$withval - if test X"$TEST_NGHTTPX" = "Xno"; then + if test "x$TEST_NGHTTPX" = "xno"; then TEST_NGHTTPX="" fi ) @@ -307,7 +307,7 @@ fi AC_ARG_WITH(test-caddy,dnl AS_HELP_STRING([--with-test-caddy=PATH],[where to find caddy for testing]), CADDY=$withval - if test X"$CADDY" = "Xno"; then + if test "x$CADDY" = "xno"; then CADDY="" fi ) @@ -323,43 +323,43 @@ fi AC_ARG_WITH(test-vsftpd,dnl AS_HELP_STRING([--with-test-vsftpd=PATH],[where to find vsftpd for testing]), VSFTPD=$withval - if test X"$VSFTPD" = "Xno"; then + if test "x$VSFTPD" = "xno"; then VSFTPD="" fi ) AC_SUBST(VSFTPD) -dnl we'd like a httpd as test server +dnl we would like an httpd as test server dnl HTTPD_ENABLED="maybe" AC_ARG_WITH(test-httpd, [AS_HELP_STRING([--with-test-httpd=PATH], [where to find httpd/apache2 for testing])], [request_httpd=$withval], [request_httpd=check]) -if test x"$request_httpd" = "xcheck" -o x"$request_httpd" = "xyes"; then +if test "x$request_httpd" = "xcheck" || test "x$request_httpd" = "xyes"; then if test -x "/usr/sbin/apache2"; then # common location on distros (debian/ubuntu) HTTPD="/usr/sbin/apache2" AC_PATH_PROG([APXS], [apxs]) - if test "x$APXS" = "x"; then + if test -z "$APXS"; then AC_MSG_NOTICE([apache2-dev not installed, httpd tests disabled]) HTTPD_ENABLED="no" fi else AC_PATH_PROG([HTTPD], [httpd]) - if test "x$HTTPD" = "x"; then + if test -z "$HTTPD"; then AC_PATH_PROG([HTTPD], [apache2]) fi AC_PATH_PROG([APXS], [apxs]) - if test "x$HTTPD" = "x"; then + if test -z "$HTTPD"; then AC_MSG_NOTICE([httpd/apache2 not in PATH, http tests disabled]) HTTPD_ENABLED="no" fi - if test "x$APXS" = "x"; then + if test -z "$APXS"; then AC_MSG_NOTICE([apxs not in PATH, http tests disabled]) HTTPD_ENABLED="no" fi fi -elif test x"$request_httpd" != "xno"; then +elif test "x$request_httpd" != "xno"; then HTTPD="${request_httpd}/bin/httpd" APXS="${request_httpd}/bin/apxs" if test ! -x "${HTTPD}"; then @@ -372,30 +372,30 @@ elif test x"$request_httpd" != "xno"; then AC_MSG_NOTICE([using HTTPD=$HTTPD for tests]) fi fi -if test x"$HTTPD_ENABLED" = "xno"; then +if test "$HTTPD_ENABLED" = "no"; then HTTPD="" APXS="" fi AC_SUBST(HTTPD) AC_SUBST(APXS) -dnl we'd like a dante as test socks server +dnl we would like a dante as test socks server dnl DANTED_ENABLED="maybe" AC_ARG_WITH(test-danted, [AS_HELP_STRING([--with-test-danted=PATH], [where to find danted socks daemon for testing])], [request_danted=$withval], [request_danted=check]) -if test x"$request_danted" = "xcheck" -o x"$request_danted" = "xyes"; then +if test "x$request_danted" = "xcheck" || test "x$request_danted" = "xyes"; then if test -x "/usr/sbin/danted"; then # common location on distros (debian/ubuntu) DANTED="/usr/sbin/danted" else AC_PATH_PROG([DANTED], [danted]) - if test "x$DANTED" = "x"; then + if test -z "$DANTED"; then AC_PATH_PROG([DANTED], [danted]) fi fi -elif test x"$request_danted" != "xno"; then +elif test "x$request_danted" != "xno"; then DANTED="${request_danted}" if test ! -x "${DANTED}"; then AC_MSG_NOTICE([danted not found as ${DANTED}, danted tests disabled]) @@ -404,13 +404,58 @@ elif test x"$request_danted" != "xno"; then AC_MSG_NOTICE([using DANTED=$DANTED for tests]) fi fi -if test x"$DANTED_ENABLED" = "xno"; then +if test "$DANTED_ENABLED" = "no"; then DANTED="" fi AC_SUBST(DANTED) +dnl we would like a sshd as test server +dnl +SSHD_ENABLED="maybe" +AC_ARG_WITH(test-sshd, [AS_HELP_STRING([--with-test-sshd=PATH], + [where to find sshd for testing])], + [request_sshd=$withval], [request_sshd=check]) +if test "x$request_sshd" = "xcheck" || test "x$request_sshd" = "xyes"; then + if test -x "/usr/sbin/sshd"; then + # common location on distros (debian/ubuntu) + SSHD="/usr/sbin/sshd" + else + AC_PATH_PROG([SSHD], [sshd]) + if test -z "$SSHD"; then + AC_PATH_PROG([SSHD], [sshd]) + fi + fi +elif test "x$request_sshd" != "xno"; then + SSHD="${request_sshd}" + if test ! -x "${SSHD}"; then + AC_MSG_NOTICE([sshd not found as ${SSHD}, sshd tests disabled]) + SSHD_ENABLED="no" + else + AC_MSG_NOTICE([using SSHD=$SSHD for tests]) + fi +fi +if test "$SSHD_ENABLED" = "no"; then + SSHD="" + SFTPD="" +else + if test -x "/usr/libexec/sftp-server"; then + # common location on macOS) + SFTPD="/usr/libexec/sftp-server" + elif test -x "/usr/lib/openssh/sftp-server"; then + # common location on debian + SFTPD="/usr/lib/openssh/sftp-server" + else + AC_PATH_PROG([SFTPD], [sftp-server]) + if test -z "$SFTPD"; then + AC_PATH_PROG([SFTPD], [sftp-server]) + fi + fi +fi +AC_SUBST(SSHD) +AC_SUBST(SFTPD) + dnl the nghttpx we might use in httpd testing -if test "x$TEST_NGHTTPX" != "x" -a "x$TEST_NGHTTPX" != "xnghttpx"; then +if test -n "$TEST_NGHTTPX" && test "x$TEST_NGHTTPX" != "xnghttpx"; then HTTPD_NGHTTPX="$TEST_NGHTTPX" else AC_PATH_PROG([HTTPD_NGHTTPX], [nghttpx], [], @@ -419,7 +464,7 @@ fi AC_SUBST(HTTPD_NGHTTPX) dnl the Caddy server we might use in testing -if test "x$TEST_CADDY" != "x"; then +if test -n "$TEST_CADDY"; then CADDY="$TEST_CADDY" else AC_PATH_PROG([CADDY], [caddy]) @@ -480,11 +525,11 @@ AM_CONDITIONAL(NOT_CURL_CI, test -z "$CURL_CI") # AM_CONDITIONAL([CURL_LT_SHLIB_USE_VERSION_INFO], - [test "x$xc_lt_shlib_use_version_info" = 'xyes']) + [test "$xc_lt_shlib_use_version_info" = "yes"]) AM_CONDITIONAL([CURL_LT_SHLIB_USE_NO_UNDEFINED], - [test "x$xc_lt_shlib_use_no_undefined" = 'xyes']) + [test "$xc_lt_shlib_use_no_undefined" = "yes"]) AM_CONDITIONAL([CURL_LT_SHLIB_USE_MIMPURE_TEXT], - [test "x$xc_lt_shlib_use_mimpure_text" = 'xyes']) + [test "$xc_lt_shlib_use_mimpure_text" = "yes"]) # # Due to libtool and automake machinery limitations of not allowing @@ -503,7 +548,7 @@ AM_CONDITIONAL([CURL_LT_SHLIB_USE_MIMPURE_TEXT], # AM_CONDITIONAL([USE_CPPFLAG_CURL_STATICLIB], - [test "x$xc_lt_build_static_only" = 'xyes']) + [test "$xc_lt_build_static_only" = "yes"]) # # Make staticlib CPPFLAG variable and its definition visible in output @@ -515,12 +560,11 @@ LIBCURL_PC_CFLAGS_PRIVATE='-DCURL_STATICLIB' AC_SUBST(LIBCURL_PC_CFLAGS_PRIVATE) LIBCURL_PC_CFLAGS= -if test "x$xc_lt_build_static_only" = 'xyes'; then +if test "$xc_lt_build_static_only" = "yes"; then LIBCURL_PC_CFLAGS="${LIBCURL_PC_CFLAGS_PRIVATE}" fi AC_SUBST([LIBCURL_PC_CFLAGS]) - dnl ********************************************************************** dnl platform/compiler/architecture specific checks/flags dnl ********************************************************************** @@ -530,12 +574,8 @@ dnl for --enable-code-coverage CURL_COVERAGE CURL_CHECK_NATIVE_WINDOWS -curl_cv_wince='no' curl_cv_winuwp='no' if test "$curl_cv_native_windows" = "yes"; then - case $host_os in - mingw32ce*) curl_cv_wince='yes';; - esac case "$CPPFLAGS" in *-DWINSTORECOMPAT*) curl_cv_winuwp='yes';; esac @@ -559,7 +599,7 @@ if test "$compiler_id" = "INTEL_UNIX_C"; then fi CURL_CFLAG_EXTRAS="" -if test X"$want_werror" = Xyes; then +if test "$want_werror" = "yes"; then CURL_CFLAG_EXTRAS="-Werror" if test "$compiler_id" = "GNU_C"; then dnl enable -pedantic-errors for GCC 5 and later, @@ -567,12 +607,12 @@ if test X"$want_werror" = Xyes; then if test "$compiler_num" -ge "500"; then CURL_CFLAG_EXTRAS="$CURL_CFLAG_EXTRAS -pedantic-errors" fi - elif test "$compiler_id" = "CLANG" -o "$compiler_id" = "APPLECLANG"; then + elif test "$compiler_id" = "CLANG" || test "$compiler_id" = "APPLECLANG"; then CURL_CFLAG_EXTRAS="$CURL_CFLAG_EXTRAS -pedantic-errors" fi fi AC_SUBST(CURL_CFLAG_EXTRAS) -AM_CONDITIONAL(CURL_WERROR, test X"$want_werror" = Xyes) +AM_CONDITIONAL(CURL_WERROR, test "$want_werror" = "yes") CURL_CHECK_COMPILER_HALT_ON_ERROR CURL_CHECK_COMPILER_ARRAY_SIZE_NEGATIVE @@ -583,8 +623,8 @@ supports_unittests=yes # cross-compilation of unit tests static library/programs fails when # libcurl shared library is built. This might be due to a libtool or # automake issue. In this case we disable unit tests. -if test "x$cross_compiling" != "xno" && - test "x$enable_shared" != "xno"; then +if test "$cross_compiling" != "no" && + test "$enable_shared" != "no"; then supports_unittests=no fi @@ -608,7 +648,7 @@ case $host_os in ;; esac -AM_CONDITIONAL(BUILD_UNITTESTS, test x$supports_unittests = xyes) +AM_CONDITIONAL(BUILD_UNITTESTS, test "$supports_unittests" = "yes") # In order to detect support of sendmmsg() and accept4(), we need to escape the POSIX # jail by defining _GNU_SOURCE or will not expose it. @@ -622,7 +662,6 @@ dnl ********************************************************************** dnl Compilation based checks should not be done before this point. dnl ********************************************************************** -CURL_CHECK_WIN32_LARGEFILE CURL_CHECK_WIN32_CRYPTO curl_cv_apple='no' @@ -630,7 +669,7 @@ case $host in *-apple-*) curl_cv_apple='yes';; esac -if test "$curl_cv_apple" = 'yes'; then +if test "$curl_cv_apple" = "yes"; then CURL_DARWIN_CFLAGS CURL_SUPPORTS_BUILTIN_AVAILABLE fi @@ -668,11 +707,11 @@ AS_HELP_STRING([--disable-unity],[Disable unity (default)]), esac ], AC_MSG_RESULT([no]) ) -if test -z "$PERL" -a "$want_unity" = 'yes'; then +if test -z "$PERL" && test "$want_unity" = "yes"; then AC_MSG_WARN([perl was not found. Will not enable unity.]) want_unity='no' fi -AM_CONDITIONAL([USE_UNITY], [test "$want_unity" = 'yes']) +AM_CONDITIONAL([USE_UNITY], [test "$want_unity" = "yes"]) dnl ************************************************************ dnl switch off particular protocols @@ -750,7 +789,7 @@ AS_HELP_STRING([--disable-ipfs],[Disable IPFS support]), CURL_DISABLE_IPFS=1 ;; *) - if test x$CURL_DISABLE_HTTP = x1; then + if test "$CURL_DISABLE_HTTP" = "1"; then AC_MSG_ERROR(HTTP support needs to be enabled in order to enable IPFS support!) else AC_MSG_RESULT(yes) @@ -758,7 +797,7 @@ AS_HELP_STRING([--disable-ipfs],[Disable IPFS support]), fi ;; esac ], - if test "x$CURL_DISABLE_HTTP" != "x1"; then + if test "$CURL_DISABLE_HTTP" != "1"; then AC_MSG_RESULT(yes) curl_ipfs_msg="enabled" else @@ -796,7 +835,7 @@ AS_HELP_STRING([--disable-ldaps],[Disable LDAPS support]), CURL_DISABLE_LDAPS=1 ;; *) - if test "x$CURL_DISABLE_LDAP" = "x1"; then + if test "$CURL_DISABLE_LDAP" = "1"; then AC_MSG_RESULT(LDAP needs to be enabled to support LDAPS) AC_DEFINE(CURL_DISABLE_LDAPS, 1, [to disable LDAPS]) CURL_DISABLE_LDAPS=1 @@ -807,7 +846,7 @@ AS_HELP_STRING([--disable-ldaps],[Disable LDAPS support]), fi ;; esac ],[ - if test "x$CURL_DISABLE_LDAP" = "x1"; then + if test "$CURL_DISABLE_LDAP" = "1"; then AC_MSG_RESULT(no) AC_DEFINE(CURL_DISABLE_LDAPS, 1, [to disable LDAPS]) CURL_DISABLE_LDAPS=1 @@ -822,27 +861,27 @@ AC_MSG_CHECKING([whether to support rtsp]) AC_ARG_ENABLE(rtsp, AS_HELP_STRING([--enable-rtsp],[Enable RTSP support]) AS_HELP_STRING([--disable-rtsp],[Disable RTSP support]), - [ case "$enableval" in - no) +[ case "$enableval" in + no) + AC_MSG_RESULT(no) + AC_DEFINE(CURL_DISABLE_RTSP, 1, [to disable RTSP]) + CURL_DISABLE_RTSP=1 + ;; + *) + if test "$CURL_DISABLE_HTTP" = "1"; then + AC_MSG_ERROR(HTTP support needs to be enabled in order to enable RTSP support!) + else + AC_MSG_RESULT(yes) + curl_rtsp_msg="enabled" + fi + ;; + esac ], + if test "$CURL_DISABLE_HTTP" != "1"; then + AC_MSG_RESULT(yes) + curl_rtsp_msg="enabled" + else AC_MSG_RESULT(no) - AC_DEFINE(CURL_DISABLE_RTSP, 1, [to disable RTSP]) - CURL_DISABLE_RTSP=1 - ;; - *) - if test x$CURL_DISABLE_HTTP = x1; then - AC_MSG_ERROR(HTTP support needs to be enabled in order to enable RTSP support!) - else - AC_MSG_RESULT(yes) - curl_rtsp_msg="enabled" - fi - ;; - esac ], - if test "x$CURL_DISABLE_HTTP" != "x1"; then - AC_MSG_RESULT(yes) - curl_rtsp_msg="enabled" - else - AC_MSG_RESULT(no) - fi + fi ) AC_MSG_CHECKING([whether to support proxies]) @@ -897,7 +936,7 @@ AS_HELP_STRING([--disable-telnet],[Disable TELNET support]), AC_MSG_RESULT(yes) ) -if test "$curl_cv_winuwp" = 'yes' -o "$curl_cv_wince" = 'yes'; then +if test "$curl_cv_winuwp" = "yes"; then AC_DEFINE(CURL_DISABLE_TELNET, 1, [to disable TELNET]) CURL_DISABLE_TELNET=1 fi @@ -1068,7 +1107,7 @@ AS_HELP_STRING([--disable-docs],[Disable documentation]), AC_MSG_RESULT(yes) BUILD_DOCS=1 ) -if test -z "$PERL" -a "x$BUILD_DOCS" != "x0"; then +if test -z "$PERL" && test "$BUILD_DOCS" != "0"; then AC_MSG_WARN([perl was not found. Will not build documentation.]) BUILD_DOCS=0 fi @@ -1112,6 +1151,22 @@ AS_HELP_STRING([--enable-libgcc],[use libgcc when linking]), AC_MSG_RESULT(no) ) +AC_MSG_CHECKING([whether to use libbacktrace]) +AC_ARG_WITH(backtrace, +AS_HELP_STRING([--enable-backtrace],[use libbacktrace when linking]), +[ case "$enableval" in + yes) + LIBS="-lbacktrace $LIBS" + AC_DEFINE(USE_BACKTRACE, 1, [if libbacktrace is in use]) + AC_MSG_RESULT(yes) + ;; + *) + AC_MSG_RESULT(no) + ;; + esac ], + AC_MSG_RESULT(no) +) + CURL_CHECK_LIB_XNET dnl gethostbyname without lib or in the nsl lib? @@ -1178,47 +1233,16 @@ if test "$HAVE_GETHOSTBYNAME" != "1"; then ]) fi -if test "$HAVE_GETHOSTBYNAME" != "1"; then - if test "$curl_cv_wince" = 'yes'; then - dnl This is for Windows CE systems - winsock_LIB="-lws2" - 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 _WIN32 - #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN - #endif - #include - #endif - ]],[[ - gethostbyname("localhost"); - ]]) - ],[ - AC_MSG_RESULT([yes]) - HAVE_GETHOSTBYNAME="1" - ],[ - AC_MSG_RESULT([no]) - winsock_LIB="" - LIBS=$my_ac_save_LIBS - ]) - fi - fi -fi - # In UWP mode gethostbyname gets detected via the core libs, but some # code (in6addr_any) still need ws2_32, so let us detect and add it. -if test "$HAVE_GETHOSTBYNAME" != "1" -o "$curl_cv_winuwp" = "yes"; then +if test "$HAVE_GETHOSTBYNAME" != "1" || test "$curl_cv_winuwp" = "yes"; then if test "$curl_cv_native_windows" = "yes"; then dnl This is for Winsock systems winsock_LIB="-lws2_32" if test "$curl_cv_winuwp" != "yes"; then winsock_LIB="$winsock_LIB -liphlpapi" fi - if test ! -z "$winsock_LIB"; then + if test -n "$winsock_LIB"; then my_ac_save_LIBS=$LIBS LIBS="$winsock_LIB $LIBS" AC_MSG_CHECKING([for gethostbyname in $winsock_LIB]) @@ -1281,7 +1305,7 @@ if test "$HAVE_GETHOSTBYNAME" != "1"; then ]) fi -if test "$HAVE_GETHOSTBYNAME" != "1" -o "${with_amissl+set}" = set; then +if test "$HAVE_GETHOSTBYNAME" != "1" || test "${with_amissl+set}" = "set"; then dnl This is for AmigaOS with bsdsocket.library - needs testing before -lnet AC_MSG_CHECKING([for gethostbyname for AmigaOS bsdsocket.library]) AC_LINK_IFELSE([ @@ -1351,10 +1375,10 @@ AS_HELP_STRING([--with-zlib=PATH],[search for zlib in PATH]) AS_HELP_STRING([--without-zlib],[disable use of zlib]), [OPT_ZLIB="$withval"]) -if test "$OPT_ZLIB" = "no"; then +if test "x$OPT_ZLIB" = "xno"; then AC_MSG_WARN([zlib disabled]) else - if test "$OPT_ZLIB" = "yes"; then + if test "x$OPT_ZLIB" = "xyes"; then OPT_ZLIB="" fi @@ -1404,7 +1428,7 @@ else [ dnl zlib.h was found HAVE_ZLIB_H="1" - dnl if the lib wasn't found already, try again with the new paths + dnl if the lib was not found already, try again with the new paths if test "$HAVE_LIBZ" != "1"; then AC_CHECK_LIB(z, gzread, [ @@ -1454,7 +1478,7 @@ else fi dnl set variable for use in automakefile(s) -AM_CONDITIONAL(HAVE_LIBZ, test x"$AMFIXLIB" = x1) +AM_CONDITIONAL(HAVE_LIBZ, test "$AMFIXLIB" = "1") AC_SUBST(ZLIB_LIBS) dnl ********************************************************************** @@ -1470,7 +1494,7 @@ AS_HELP_STRING([--with-brotli=PATH],[Where to look for brotli, PATH points to th AS_HELP_STRING([--without-brotli], [disable BROTLI]), OPT_BROTLI=$withval) -if test X"$OPT_BROTLI" != Xno; then +if test "x$OPT_BROTLI" != "xno"; then dnl backup the pre-brotli variables CLEANLDFLAGS="$LDFLAGS" CLEANLDFLAGSPC="$LDFLAGSPC" @@ -1529,18 +1553,18 @@ if test X"$OPT_BROTLI" != Xno; then AC_DEFINE(HAVE_BROTLI, 1, [if BROTLI is in use]) ) - if test X"$OPT_BROTLI" != Xoff && + if test "x$OPT_BROTLI" != "xoff" && test "$HAVE_BROTLI" != "1"; then AC_MSG_ERROR([BROTLI libs and/or directories were not found where specified!]) fi if test "$HAVE_BROTLI" = "1"; then if test -n "$DIR_BROTLI"; then - dnl when the brotli shared libs were found in a path that the run-time - dnl linker doesn't search through, we need to add it to CURL_LIBRARY_PATH + dnl when the brotli shared libs were found in a path that the runtime + dnl linker does not search through, we need to add it to CURL_LIBRARY_PATH dnl to prevent further configure tests to fail due to this - if test "x$cross_compiling" != "xyes"; then + if test "$cross_compiling" != "yes"; then CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$DIR_BROTLI" export CURL_LIBRARY_PATH AC_MSG_NOTICE([Added $DIR_BROTLI to CURL_LIBRARY_PATH]) @@ -1567,7 +1591,7 @@ AS_HELP_STRING([--with-zstd=PATH],[Where to look for libzstd, PATH points to the AS_HELP_STRING([--without-zstd], [disable libzstd]), OPT_ZSTD=$withval) -if test X"$OPT_ZSTD" != Xno; then +if test "x$OPT_ZSTD" != "xno"; then dnl backup the pre-zstd variables CLEANLDFLAGS="$LDFLAGS" CLEANLDFLAGSPC="$LDFLAGSPC" @@ -1618,19 +1642,19 @@ if test X"$OPT_ZSTD" != Xno; then AC_DEFINE(HAVE_ZSTD, 1, [if libzstd is in use]) ) - if test X"$OPT_ZSTD" != Xoff && + if test "x$OPT_ZSTD" != "xoff" && test "$HAVE_ZSTD" != "1"; then AC_MSG_ERROR([libzstd was not found where specified!]) fi if test "$HAVE_ZSTD" = "1"; then if test -n "$DIR_ZSTD"; then - dnl when the zstd shared lib were found in a path that the run-time - dnl linker doesn't search through, we need to add it to + dnl when the zstd shared lib were found in a path that the runtime + dnl linker does not search through, we need to add it to dnl CURL_LIBRARY_PATH to prevent further configure tests to fail due to dnl this - if test "x$cross_compiling" != "xyes"; then + if test "$cross_compiling" != "yes"; then CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$DIR_ZSTD" export CURL_LIBRARY_PATH AC_MSG_NOTICE([Added $DIR_ZSTD to CURL_LIBRARY_PATH]) @@ -1694,11 +1718,7 @@ AS_HELP_STRING([--disable-ipv6],[Disable IPv6 support]), ) ) -if test "$curl_cv_wince" = 'yes'; then - ipv6=no -fi - -if test "$ipv6" = yes; then +if test "$ipv6" = "yes"; then curl_ipv6_msg="enabled" AC_DEFINE(USE_IPV6, 1, [Define if you want to enable IPv6 support]) IPV6_ENABLED=1 @@ -1756,7 +1776,7 @@ int main(int argc, char **argv) ],[ curl_cv_writable_argv=cross ]) -if test "$curl_cv_writable_argv" = 'cross' -a "$curl_cv_apple" = 'yes'; then +if test "$curl_cv_writable_argv" = "cross" && test "$curl_cv_apple" = "yes"; then curl_cv_writable_argv=yes fi case $curl_cv_writable_argv in @@ -1797,9 +1817,9 @@ AC_ARG_WITH(gssapi-libs, AC_ARG_WITH(gssapi, AS_HELP_STRING([--with-gssapi=DIR], [Where to look for GSS-API]), [ GSSAPI_ROOT="$withval" - if test x"$GSSAPI_ROOT" != xno; then + if test "$GSSAPI_ROOT" != "no"; then want_gss="yes" - if test x"$GSSAPI_ROOT" = xyes; then + if test "$GSSAPI_ROOT" = "yes"; then dnl if yes, then use default root GSSAPI_ROOT="/usr" fi @@ -1811,16 +1831,16 @@ AC_ARG_WITH(gssapi, save_CPPFLAGS="$CPPFLAGS" AC_MSG_CHECKING([if GSS-API support is requested]) -if test x"$want_gss" = xyes; then +if test "$want_gss" = "yes"; then AC_MSG_RESULT(yes) - if test $GSSAPI_ROOT != "/usr"; then + if test "$GSSAPI_ROOT" != "/usr"; then CURL_CHECK_PKGCONFIG(mit-krb5-gssapi, $GSSAPI_ROOT/lib/pkgconfig) else CURL_CHECK_PKGCONFIG(mit-krb5-gssapi) fi if test -z "$GSSAPI_INCS"; then - if test -n "$host_alias" -a -f "$GSSAPI_ROOT/bin/$host_alias-krb5-config"; then + if test -n "$host_alias" && test -f "$GSSAPI_ROOT/bin/$host_alias-krb5-config"; then GSSAPI_INCS=`$GSSAPI_ROOT/bin/$host_alias-krb5-config --cflags gssapi` elif test "$PKGCONFIG" != "no"; then GSSAPI_INCS=`$PKGCONFIG --cflags mit-krb5-gssapi` @@ -1845,7 +1865,7 @@ if test x"$want_gss" = xyes; then [gssapi/gssapi.h gssapi/gssapi_generic.h gssapi/gssapi_krb5.h], [], [not_mit=1]) - if test "x$not_mit" = "x1"; then + if test "$not_mit" = "1"; then dnl MIT not found AC_MSG_ERROR([MIT or GNU GSS library required, but not found]) fi @@ -1854,7 +1874,7 @@ if test x"$want_gss" = xyes; then else AC_MSG_RESULT(no) fi -if test x"$want_gss" = xyes; then +if test "$want_gss" = "yes"; then AC_DEFINE(HAVE_GSSAPI, 1, [if you have GSS-API libraries]) HAVE_GSSAPI=1 curl_gss_msg="enabled (MIT Kerberos)" @@ -1867,16 +1887,16 @@ if test x"$want_gss" = xyes; then LIBS="-lgss $LIBS" link_pkgconfig=1 elif test -z "$GSSAPI_LIB_DIR"; then - if test "$curl_cv_apple" = 'yes'; then + if test "$curl_cv_apple" = "yes"; then LIBS="-lgssapi_krb5 -lresolv $LIBS" else - if test $GSSAPI_ROOT != "/usr"; then + if test "$GSSAPI_ROOT" != "/usr"; then CURL_CHECK_PKGCONFIG(mit-krb5-gssapi, $GSSAPI_ROOT/lib/pkgconfig) else CURL_CHECK_PKGCONFIG(mit-krb5-gssapi) fi - if test -n "$host_alias" -a -f "$GSSAPI_ROOT/bin/$host_alias-krb5-config"; then - dnl krb5-config doesn't have --libs-only-L or similar, put everything + if test -n "$host_alias" && test -f "$GSSAPI_ROOT/bin/$host_alias-krb5-config"; then + dnl krb5-config does not have --libs-only-L or similar, put everything dnl into LIBS gss_libs=`$GSSAPI_ROOT/bin/$host_alias-krb5-config --libs gssapi` LIBS="$gss_libs $LIBS" @@ -1885,7 +1905,7 @@ if test x"$want_gss" = xyes; then LIBS="$gss_libs $LIBS" link_pkgconfig=1 elif test -f "$KRB5CONFIG"; then - dnl krb5-config doesn't have --libs-only-L or similar, put everything + dnl krb5-config does not have --libs-only-L or similar, put everything dnl into LIBS gss_libs=`$KRB5CONFIG --libs gssapi` LIBS="$gss_libs $LIBS" @@ -1910,7 +1930,7 @@ if test x"$want_gss" = xyes; then fi fi gss_version="" - if test -n "$host_alias" -a -f "$GSSAPI_ROOT/bin/$host_alias-krb5-config"; then + if test -n "$host_alias" && test -f "$GSSAPI_ROOT/bin/$host_alias-krb5-config"; then gss_version=`$GSSAPI_ROOT/bin/$host_alias-krb5-config --version | $SED 's/Kerberos 5 release //'` elif test "$PKGCONFIG" != "no"; then gss_version=`$PKGCONFIG --modversion mit-krb5-gssapi` @@ -1944,7 +1964,7 @@ else CPPFLAGS="$save_CPPFLAGS" fi -if test x"$want_gss" = xyes; then +if test "$want_gss" = "yes"; then AC_MSG_CHECKING([if we can link against GSS-API library]) AC_LINK_IFELSE([ AC_LANG_FUNC_LINK_TRY([gss_init_sec_context]) @@ -1957,11 +1977,11 @@ if test x"$want_gss" = xyes; then fi build_libstubgss=no -if test x"$want_gss" = "xyes"; then +if test "$want_gss" = "yes"; then build_libstubgss=yes fi -AM_CONDITIONAL(BUILD_STUB_GSS, test "x$build_libstubgss" = "xyes") +AM_CONDITIONAL(BUILD_STUB_GSS, test "$build_libstubgss" = "yes") dnl ------------------------------------------------------------- dnl parse --with-default-ssl-backend so it can be validated below @@ -1998,15 +2018,12 @@ CURL_WITH_RUSTLS CURL_WITH_APPLE_SECTRUST dnl link required libraries for USE_WIN32_CRYPTO or SCHANNEL_ENABLED -if test "x$USE_WIN32_CRYPTO" = "x1" -o "x$SCHANNEL_ENABLED" = "x1"; then - LIBS="-lcrypt32 $LIBS" - if test "$curl_cv_wince" = 'no'; then - LIBS="-ladvapi32 $LIBS" - fi +if test "$USE_WIN32_CRYPTO" = "1" || test "$SCHANNEL_ENABLED" = "1"; then + LIBS="-ladvapi32 -lcrypt32 $LIBS" fi dnl link bcrypt for BCryptGenRandom() (used when building for Vista or newer) -if test "x$curl_cv_native_windows" = "xyes" -a "$curl_cv_wince" = 'no'; then +if test "$curl_cv_native_windows" = "yes"; then LIBS="-lbcrypt $LIBS" fi @@ -2041,13 +2058,13 @@ if test -n "$ssl_backends"; then curl_ssl_msg="enabled ($ssl_backends)" fi -if test no = "$VALID_DEFAULT_SSL_BACKEND"; then +if test "$VALID_DEFAULT_SSL_BACKEND" = "no"; then if test -n "$SSL_ENABLED"; then AC_MSG_ERROR([Default SSL backend $DEFAULT_SSL_BACKEND not enabled!]) else AC_MSG_ERROR([Default SSL backend requires SSL!]) fi -elif test yes = "$VALID_DEFAULT_SSL_BACKEND"; then +elif test "$VALID_DEFAULT_SSL_BACKEND" = "yes"; then AC_DEFINE_UNQUOTED([CURL_DEFAULT_SSL_BACKEND], ["$DEFAULT_SSL_BACKEND"], [Default SSL backend]) fi @@ -2060,7 +2077,7 @@ if test -n "$check_for_ca_bundle"; then CURL_CHECK_CA_EMBED fi -AM_CONDITIONAL(CURL_CA_EMBED_SET, test "x$CURL_CA_EMBED" != "x") +AM_CONDITIONAL(CURL_CA_EMBED_SET, test -n "$CURL_CA_EMBED") dnl ---------------------- dnl check unsafe CA search @@ -2117,7 +2134,7 @@ AS_HELP_STRING([--with-libpsl=PATH],[Where to look for libpsl, PATH points to th AS_HELP_STRING([--without-libpsl], [disable LIBPSL]), OPT_LIBPSL=$withval) -if test X"$OPT_LIBPSL" != Xno; then +if test "x$OPT_LIBPSL" != "xno"; then dnl backup the pre-libpsl variables CLEANLDFLAGS="$LDFLAGS" CLEANLDFLAGSPC="$LDFLAGSPC" @@ -2179,7 +2196,6 @@ if test X"$OPT_LIBPSL" != Xno; then fi AM_CONDITIONAL([USE_LIBPSL], [test "$curl_psl_msg" = "enabled"]) - dnl ********************************************************************** dnl Check for libgsasl dnl ********************************************************************** @@ -2190,7 +2206,7 @@ AS_HELP_STRING([--with-libgsasl=PATH],[Where to look for libgsasl, PATH points t AS_HELP_STRING([--without-libgsasl], [disable libgsasl support for SCRAM]), OPT_LIBGSASL=$withval) -if test "$OPT_LIBGSASL" != no; then +if test "x$OPT_LIBGSASL" != "xno"; then dnl backup the pre-libgsasl variables CLEANLDFLAGS="$LDFLAGS" CLEANLDFLAGSPC="$LDFLAGSPC" @@ -2263,14 +2279,13 @@ AS_HELP_STRING([--with-libssh2=PATH],[Where to look for libssh2, PATH points to AS_HELP_STRING([--with-libssh2], [enable libssh2]), OPT_LIBSSH2=$withval, OPT_LIBSSH2=no) - OPT_LIBSSH=off AC_ARG_WITH(libssh,dnl AS_HELP_STRING([--with-libssh=PATH],[Where to look for libssh, PATH points to the libssh installation; when possible, set the PKG_CONFIG_PATH environment variable instead of using this option]) AS_HELP_STRING([--with-libssh], [enable libssh]), OPT_LIBSSH=$withval, OPT_LIBSSH=no) -if test X"$OPT_LIBSSH2" != Xno; then +if test "x$OPT_LIBSSH2" != "xno"; then dnl backup the pre-libssh2 variables CLEANLDFLAGS="$LDFLAGS" CLEANLDFLAGSPC="$LDFLAGSPC" @@ -2322,18 +2337,18 @@ if test X"$OPT_LIBSSH2" != Xno; then USE_LIBSSH2=1 ) - if test X"$OPT_LIBSSH2" != Xoff && + if test "x$OPT_LIBSSH2" != "xoff" && test "$USE_LIBSSH2" != "1"; then AC_MSG_ERROR([libssh2 libs and/or directories were not found where specified!]) fi if test "$USE_LIBSSH2" = "1"; then if test -n "$DIR_SSH2"; then - dnl when the libssh2 shared libs were found in a path that the run-time - dnl linker doesn't search through, we need to add it to CURL_LIBRARY_PATH + dnl when the libssh2 shared libs were found in a path that the runtime + dnl linker does not search through, we need to add it to CURL_LIBRARY_PATH dnl to prevent further configure tests to fail due to this - if test "x$cross_compiling" != "xyes"; then + if test "$cross_compiling" != "yes"; then CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$DIR_SSH2" export CURL_LIBRARY_PATH AC_MSG_NOTICE([Added $DIR_SSH2 to CURL_LIBRARY_PATH]) @@ -2347,7 +2362,7 @@ if test X"$OPT_LIBSSH2" != Xno; then CPPFLAGS=$CLEANCPPFLAGS LIBS=$CLEANLIBS fi -elif test X"$OPT_LIBSSH" != Xno; then +elif test "x$OPT_LIBSSH" != "xno"; then dnl backup the pre-libssh variables CLEANLDFLAGS="$LDFLAGS" CLEANLDFLAGSPC="$LDFLAGSPC" @@ -2398,7 +2413,7 @@ elif test X"$OPT_LIBSSH" != Xno; then USE_LIBSSH=1 ) - if test X"$OPT_LIBSSH" != Xoff && + if test "x$OPT_LIBSSH" != "xoff" && test "$USE_LIBSSH" != "1"; then AC_MSG_ERROR([libssh libs and/or directories were not found where specified!]) fi @@ -2409,11 +2424,11 @@ elif test X"$OPT_LIBSSH" != Xno; then LIBS="-liphlpapi $LIBS" fi if test -n "$DIR_SSH"; then - dnl when the libssh shared libs were found in a path that the run-time - dnl linker doesn't search through, we need to add it to CURL_LIBRARY_PATH + dnl when the libssh shared libs were found in a path that the runtime + dnl linker does not search through, we need to add it to CURL_LIBRARY_PATH dnl to prevent further configure tests to fail due to this - if test "x$cross_compiling" != "xyes"; then + if test "$cross_compiling" != "yes"; then CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$DIR_SSH" export CURL_LIBRARY_PATH AC_MSG_NOTICE([Added $DIR_SSH to CURL_LIBRARY_PATH]) @@ -2463,7 +2478,7 @@ case "$OPT_LDAP" in want_ldap="yes" ;; off) - dnl no --with-ldap option given, don't change anything + dnl no --with-ldap option given, do not change anything want_ldap="default" ;; *) @@ -2483,14 +2498,14 @@ case "$OPT_LDAP" in ;; esac -if test x$CURL_DISABLE_LDAP != x1 && test "$want_ldap" != "no"; then +if test "$CURL_DISABLE_LDAP" != "1" && test "$want_ldap" != "no"; then CURL_CHECK_HEADER_LBER CURL_CHECK_HEADER_LDAP CURL_CHECK_HEADER_LDAP_SSL if test -z "$LDAPLIBNAME"; then - if test "$curl_cv_native_windows" = "yes" -a "$curl_cv_winuwp" != "yes"; then + if test "$curl_cv_native_windows" = "yes" && test "$curl_cv_winuwp" != "yes"; then dnl Windows uses a single and unique LDAP library name LDAPLIBNAME="wldap32" LBERLIBNAME="no" @@ -2499,7 +2514,7 @@ if test x$CURL_DISABLE_LDAP != x1 && test "$want_ldap" != "no"; then if test "$LDAPLIBNAME"; then dnl If we have both LDAP and LBER library names, check if we need both - if test "$LBERLIBNAME" -a "$LBERLIBNAME" != "no"; then + if test "$LBERLIBNAME" && test "$LBERLIBNAME" != "no"; then dnl Try LDAP first, then with LBER if needed AC_CHECK_LIB("$LDAPLIBNAME", ldap_init, [ldap_lib_ok=yes], [ldap_lib_ok=no]) if test "$ldap_lib_ok" = "no"; then @@ -2520,7 +2535,7 @@ if test x$CURL_DISABLE_LDAP != x1 && test "$want_ldap" != "no"; then if test "$ldap_lib_ok" = "no"; then if test -n "$ldap_askedfor"; then - AC_MSG_ERROR([couldn't detect the LDAP libraries]) + AC_MSG_ERROR([could not detect the LDAP libraries]) fi AC_MSG_WARN(["$LDAPLIBNAME" is not an LDAP library: LDAP disabled]) AC_DEFINE(CURL_DISABLE_LDAP, 1, [to disable LDAP]) @@ -2538,7 +2553,7 @@ if test x$CURL_DISABLE_LDAP != x1 && test "$want_ldap" != "no"; then case X-"$curl_cv_ldap_LIBS" in X-unknown) if test -n "$ldap_askedfor"; then - AC_MSG_ERROR([couldn't detect the LDAP libraries]) + AC_MSG_ERROR([could not detect the LDAP libraries]) fi AC_MSG_WARN([Cannot find libraries for LDAP support: LDAP disabled]) AC_DEFINE(CURL_DISABLE_LDAP, 1, [to disable LDAP]) @@ -2554,15 +2569,15 @@ if test x$CURL_DISABLE_LDAP != x1 && test "$want_ldap" != "no"; then fi fi -if test x$CURL_DISABLE_LDAP != x1; then +if test "$CURL_DISABLE_LDAP" != "1"; then dnl Add to library path if needed if test -n "$DIR_LDAP"; then - dnl when the ldap shared lib were found in a path that the run-time - dnl linker doesn't search through, we need to add it to + dnl when the ldap shared lib were found in a path that the runtime + dnl linker does not search through, we need to add it to dnl CURL_LIBRARY_PATH to prevent further configure tests to fail due to dnl this - if test "x$cross_compiling" != "xyes"; then + if test "$cross_compiling" != "yes"; then CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$DIR_LDAP" export CURL_LIBRARY_PATH AC_MSG_NOTICE([Added $DIR_LDAP to CURL_LIBRARY_PATH]) @@ -2570,10 +2585,10 @@ if test x$CURL_DISABLE_LDAP != x1; then fi if test "$LBERLIBNAME"; then - dnl If name is "no" then don't define this library at all - dnl (it's only needed if libldap.so's dependencies are broken). + dnl If name is "no" then do not define this library at all + dnl (it is only needed if libldap.so's dependencies are broken). dnl Skip this check if we already determined we need both libraries above - if test "$LBERLIBNAME" != "no" -a "$ldap_lib_ok" != "yes"; then + if test "$LBERLIBNAME" != "no" && test "$ldap_lib_ok" != "yes"; then AC_CHECK_LIB("$LBERLIBNAME", ber_free,, [ AC_MSG_WARN(["$LBERLIBNAME" is not an LBER library: LDAP disabled]) AC_DEFINE(CURL_DISABLE_LDAP, 1, [to disable LDAP]) @@ -2590,7 +2605,7 @@ if test x$CURL_DISABLE_LDAP != x1; then fi fi -if test x$CURL_DISABLE_LDAP != x1; then +if test "$CURL_DISABLE_LDAP" != "1"; then AC_CHECK_FUNCS([ldap_url_parse \ ldap_init_fd]) @@ -2598,7 +2613,7 @@ if test x$CURL_DISABLE_LDAP != x1; then curl_ldap_msg="enabled (winldap)" AC_DEFINE(USE_WIN32_LDAP, 1, [Use Windows LDAP implementation]) else - if test "x$ac_cv_func_ldap_init_fd" = "xyes"; then + if test "$ac_cv_func_ldap_init_fd" = "yes"; then curl_ldap_msg="enabled (OpenLDAP)" AC_DEFINE(USE_OPENLDAP, 1, [Use OpenLDAP-specific code]) USE_OPENLDAP=1 @@ -2608,7 +2623,7 @@ if test x$CURL_DISABLE_LDAP != x1; then fi fi -if test x$CURL_DISABLE_LDAPS != x1; then +if test "$CURL_DISABLE_LDAPS" != "1"; then curl_ldaps_msg="enabled" fi @@ -2623,7 +2638,7 @@ AS_HELP_STRING([--with-librtmp=PATH],[Where to look for librtmp, PATH points to AS_HELP_STRING([--without-librtmp], [disable LIBRTMP]), OPT_LIBRTMP=$withval) -if test X"$OPT_LIBRTMP" != Xno; then +if test "x$OPT_LIBRTMP" != "xno"; then dnl backup the pre-librtmp variables CLEANLDFLAGS="$LDFLAGS" CLEANLDFLAGSPC="$LDFLAGSPC" @@ -2646,7 +2661,6 @@ if test X"$OPT_LIBRTMP" != Xno; then dnl a pkgconfig file AC_MSG_ERROR([--librtmp was specified but could not find librtmp pkgconfig file.]) fi - ;; off) dnl no --with-librtmp option given, just check default places @@ -2687,7 +2701,7 @@ if test X"$OPT_LIBRTMP" != Xno; then LIBS=$CLEANLIBS ) - if test X"$OPT_LIBRTMP" != Xoff && + if test "x$OPT_LIBRTMP" != "xoff" && test "$USE_LIBRTMP" != "1"; then AC_MSG_ERROR([librtmp libs and/or directories were not found where specified!]) fi @@ -2717,17 +2731,17 @@ AS_HELP_STRING([--disable-versioned-symbols], [Disable versioned symbols in shar AC_MSG_RESULT(yes) if test "x$enableval" != "xyes"; then versioned_symbols_flavour="$enableval" - elif test "x$CURL_WITH_MULTI_SSL" = "x1"; then + elif test "$CURL_WITH_MULTI_SSL" = "1"; then versioned_symbols_flavour="MULTISSL_" - elif test "x$OPENSSL_ENABLED" = "x1"; then + elif test "$OPENSSL_ENABLED" = "1"; then versioned_symbols_flavour="OPENSSL_" - elif test "x$MBEDTLS_ENABLED" = "x1"; then + elif test "$MBEDTLS_ENABLED" = "1"; then versioned_symbols_flavour="MBEDTLS_" - elif test "x$WOLFSSL_ENABLED" = "x1"; then + elif test "$WOLFSSL_ENABLED" = "1"; then versioned_symbols_flavour="WOLFSSL_" - elif test "x$GNUTLS_ENABLED" = "x1"; then + elif test "$GNUTLS_ENABLED" = "1"; then versioned_symbols_flavour="GNUTLS_" - elif test "x$RUSTLS_ENABLED" = "x1"; then + elif test "$RUSTLS_ENABLED" = "1"; then versioned_symbols_flavour="RUSTLS_" else versioned_symbols_flavour="" @@ -2745,19 +2759,15 @@ AS_HELP_STRING([--disable-versioned-symbols], [Disable versioned symbols in shar AC_SUBST([CURL_LIBCURL_VERSIONED_SYMBOLS_PREFIX], ["$versioned_symbols_flavour"]) AC_SUBST([CURL_LIBCURL_VERSIONED_SYMBOLS_SONAME], ["4"]) dnl Keep in sync with VERSIONCHANGE - VERSIONDEL in lib/Makefile.soname AM_CONDITIONAL([CURL_LT_SHLIB_USE_VERSIONED_SYMBOLS], - [test "x$versioned_symbols" = 'xyes']) + [test "$versioned_symbols" = "yes"]) dnl ---------------------------- dnl check Windows Unicode option dnl ---------------------------- -if test "$curl_cv_wince" = 'yes'; then - want_winuni="yes" -else - want_winuni="no" -fi +want_winuni="no" if test "$curl_cv_native_windows" = "yes"; then - if test "$curl_cv_winuwp" = 'yes'; then + if test "$curl_cv_winuwp" = "yes"; then want_winuni="yes" else AC_MSG_CHECKING([whether to enable Windows Unicode (Windows native builds only)]) @@ -2789,7 +2799,7 @@ dnl check WinIDN option before other IDN libraries dnl ------------------------------------------------- tst_links_winidn='no' -if test "$curl_cv_native_windows" = 'yes'; then +if test "$curl_cv_native_windows" = "yes"; then AC_MSG_CHECKING([whether to enable Windows native IDN (Windows native builds only)]) OPT_WINIDN="default" AC_ARG_WITH(winidn, @@ -2879,7 +2889,7 @@ dnl Check for the presence of AppleIDN dnl ********************************************************************** tst_links_appleidn='no' -if test "$curl_cv_apple" = 'yes'; then +if test "$curl_cv_apple" = "yes"; then AC_MSG_CHECKING([whether to build with Apple IDN]) OPT_IDN="default" AC_ARG_WITH(apple-idn, @@ -2918,10 +2928,10 @@ AC_ARG_WITH(libidn2, AS_HELP_STRING([--with-libidn2=PATH],[Enable libidn2 usage]) AS_HELP_STRING([--without-libidn2],[Disable libidn2 usage]), [OPT_IDN=$withval]) -if test "x$tst_links_winidn" = "xyes"; then +if test "$tst_links_winidn" = "yes"; then want_idn="no" AC_MSG_RESULT([no (using WinIDN instead)]) -elif test "x$tst_links_appleidn" = "xyes"; then +elif test "$tst_links_appleidn" = "yes"; then want_idn="no" AC_MSG_RESULT([no (using AppleIDN instead)]) else @@ -3029,7 +3039,7 @@ if test "$want_idn" = "yes"; then IDN_ENABLED=1 curl_idn_msg="enabled (libidn2)" - if test -n "$IDN_DIR" -a "x$cross_compiling" != "xyes"; then + if test -n "$IDN_DIR" && test "$cross_compiling" != "yes"; then CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$IDN_DIR" export CURL_LIBRARY_PATH AC_MSG_NOTICE([Added $IDN_DIR to CURL_LIBRARY_PATH]) @@ -3051,7 +3061,7 @@ dnl ********************************************************************** OPT_H2="yes" -if test "x$disable_http" = "xyes"; then +if test "$disable_http" = "yes"; then # without HTTP nghttp2 is no use OPT_H2="no" fi @@ -3079,7 +3089,7 @@ case "$OPT_H2" in ;; esac -if test X"$want_nghttp2" != Xno; then +if test "$want_nghttp2" != "no"; then dnl backup the pre-nghttp2 variables CLEANLDFLAGS="$LDFLAGS" CLEANLDFLAGSPC="$LDFLAGSPC" @@ -3102,12 +3112,12 @@ if test X"$want_nghttp2" != Xno; then AC_MSG_NOTICE([-L is $LD_H2]) DIR_H2=`echo $LD_H2 | $SED -e 's/^-L//'` - elif test x"$want_nghttp2_path" != x; then + elif test -n "$want_nghttp2_path"; then LIB_H2="-lnghttp2" LD_H2=-L${want_nghttp2_path}/lib$libsuff CPP_H2=-I${want_nghttp2_path}/include DIR_H2=${want_nghttp2_path}/lib$libsuff - elif test X"$want_nghttp2" != Xdefault; then + elif test "$want_nghttp2" != "default"; then dnl no nghttp2 pkg-config found and no custom directory specified, dnl deal with it AC_MSG_ERROR([--with-nghttp2 was specified but could not find libnghttp2 pkg-config file.]) @@ -3149,7 +3159,7 @@ dnl ********************************************************************** OPT_TCP2="no" -if test "x$disable_http" = "xyes"; then +if test "$disable_http" = "yes"; then # without HTTP, ngtcp2 is no use OPT_TCP2="no" fi @@ -3176,7 +3186,7 @@ case "$OPT_TCP2" in esac curl_tcp2_msg="no (--with-ngtcp2)" -if test X"$want_tcp2" != Xno; then +if test "$want_tcp2" != "no"; then if test "$QUIC_ENABLED" != "yes"; then AC_MSG_ERROR([the detected TLS library does not support QUIC, making --with-ngtcp2 a no-no]) @@ -3208,7 +3218,7 @@ if test X"$want_tcp2" != Xno; then CPPFLAGS="$CPPFLAGS $CPP_TCP2" LIBS="$LIB_TCP2 $LIBS" - if test "x$cross_compiling" != "xyes"; then + if test "$cross_compiling" != "yes"; then DIR_TCP2=`echo $LD_TCP2 | $SED -e 's/^-L//'` fi AC_CHECK_LIB(ngtcp2, ngtcp2_conn_client_new_versioned, @@ -3231,7 +3241,7 @@ if test X"$want_tcp2" != Xno; then else dnl no ngtcp2 pkg-config found, deal with it - if test X"$want_tcp2" != Xdefault; then + if test "$want_tcp2" != "default"; 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 pkg-config file.]) @@ -3239,7 +3249,8 @@ if test X"$want_tcp2" != Xno; then fi fi -if test "x$USE_NGTCP2" = "x1" -a "x$OPENSSL_ENABLED" = "x1" -a "$HAVE_LIBRESSL" = "1"; then +if test "$USE_NGTCP2" = "1" && test "$OPENSSL_ENABLED" = "1" && test "$HAVE_LIBRESSL" = "1"; then + dnl backup the pre-ngtcp2_crypto_libressl variables CLEANLDFLAGS="$LDFLAGS" CLEANLDFLAGSPC="$LDFLAGSPC" @@ -3266,7 +3277,7 @@ if test "x$USE_NGTCP2" = "x1" -a "x$OPENSSL_ENABLED" = "x1" -a "$HAVE_LIBRESSL" CPPFLAGS="$CPPFLAGS $CPP_NGTCP2_CRYPTO_LIBRESSL" LIBS="$LIB_NGTCP2_CRYPTO_LIBRESSL $LIBS" - if test "x$cross_compiling" != "xyes"; then + if test "$cross_compiling" != "yes"; then DIR_NGTCP2_CRYPTO_LIBRESSL=`echo $LD_NGTCP2_CRYPTO_LIBRESSL | $SED -e 's/^-L//'` fi AC_CHECK_LIB(ngtcp2_crypto_libressl, ngtcp2_crypto_recv_client_initial_cb, @@ -3288,7 +3299,7 @@ if test "x$USE_NGTCP2" = "x1" -a "x$OPENSSL_ENABLED" = "x1" -a "$HAVE_LIBRESSL" else dnl no ngtcp2_crypto_libressl pkg-config found, deal with it - if test X"$want_tcp2" != Xdefault; then + if test "$want_tcp2" != "default"; then dnl To avoid link errors, we do not allow --with-ngtcp2 without dnl a pkgconfig file AC_MSG_WARN([--with-ngtcp2 was specified but could not find ngtcp2_crypto_libressl pkg-config file.]) @@ -3298,8 +3309,9 @@ if test "x$USE_NGTCP2" = "x1" -a "x$OPENSSL_ENABLED" = "x1" -a "$HAVE_LIBRESSL" fi fi -if test "x$USE_NGTCP2" = "x1" -a "x$OPENSSL_ENABLED" = "x1" -a "$HAVE_LIBRESSL" != "1" -a \ - "x$OPENSSL_IS_BORINGSSL" != "x1" -a "x$OPENSSL_QUIC_API2" != "x1"; then +if test "$USE_NGTCP2" = "1" && test "$OPENSSL_ENABLED" = "1" && test "$OPENSSL_IS_BORINGSSL" != "1" && + test "$OPENSSL_QUIC_API2" != "1"; then + dnl backup the pre-ngtcp2_crypto_quictls variables CLEANLDFLAGS="$LDFLAGS" CLEANLDFLAGSPC="$LDFLAGSPC" @@ -3326,7 +3338,7 @@ if test "x$USE_NGTCP2" = "x1" -a "x$OPENSSL_ENABLED" = "x1" -a "$HAVE_LIBRESSL" CPPFLAGS="$CPPFLAGS $CPP_NGTCP2_CRYPTO_QUICTLS" LIBS="$LIB_NGTCP2_CRYPTO_QUICTLS $LIBS" - if test "x$cross_compiling" != "xyes"; then + if test "$cross_compiling" != "yes"; then DIR_NGTCP2_CRYPTO_QUICTLS=`echo $LD_NGTCP2_CRYPTO_QUICTLS | $SED -e 's/^-L//'` fi AC_CHECK_LIB(ngtcp2_crypto_quictls, ngtcp2_crypto_recv_client_initial_cb, @@ -3348,7 +3360,7 @@ if test "x$USE_NGTCP2" = "x1" -a "x$OPENSSL_ENABLED" = "x1" -a "$HAVE_LIBRESSL" else dnl no ngtcp2_crypto_quictls pkg-config found, deal with it - if test X"$want_tcp2" != Xdefault; then + if test "$want_tcp2" != "default"; 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_quictls pkg-config file.]) @@ -3356,8 +3368,9 @@ if test "x$USE_NGTCP2" = "x1" -a "x$OPENSSL_ENABLED" = "x1" -a "$HAVE_LIBRESSL" fi fi -if test "x$USE_NGTCP2" = "x1" -a "x$OPENSSL_ENABLED" = "x1" -a \ - "x$OPENSSL_IS_BORINGSSL" != "x1" -a "x$OPENSSL_QUIC_API2" = "x1"; then +if test "$USE_NGTCP2" = "1" && test "$OPENSSL_ENABLED" = "1" && test "$OPENSSL_IS_BORINGSSL" != "1" && + test "$OPENSSL_QUIC_API2" = "1"; then + dnl backup the pre-ngtcp2_crypto_ossl variables CLEANLDFLAGS="$LDFLAGS" CLEANLDFLAGSPC="$LDFLAGSPC" @@ -3384,7 +3397,7 @@ if test "x$USE_NGTCP2" = "x1" -a "x$OPENSSL_ENABLED" = "x1" -a \ CPPFLAGS="$CPPFLAGS $CPP_NGTCP2_CRYPTO_OSSL" LIBS="$LIB_NGTCP2_CRYPTO_OSSL $LIBS" - if test "x$cross_compiling" != "xyes"; then + if test "$cross_compiling" != "yes"; then DIR_NGTCP2_CRYPTO_OSSL=`echo $LD_NGTCP2_CRYPTO_OSSL | $SED -e 's/^-L//'` fi AC_CHECK_LIB(ngtcp2_crypto_ossl, ngtcp2_crypto_recv_client_initial_cb, @@ -3407,7 +3420,7 @@ if test "x$USE_NGTCP2" = "x1" -a "x$OPENSSL_ENABLED" = "x1" -a \ else dnl no ngtcp2_crypto_ossl pkg-config found, deal with it - if test X"$want_tcp2" != Xdefault; then + if test "$want_tcp2" != "default"; 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_ossl pkg-config file.]) @@ -3415,7 +3428,8 @@ if test "x$USE_NGTCP2" = "x1" -a "x$OPENSSL_ENABLED" = "x1" -a \ fi fi -if test "x$USE_NGTCP2" = "x1" -a "x$OPENSSL_ENABLED" = "x1" -a "x$OPENSSL_IS_BORINGSSL" = "x1"; then +if test "$USE_NGTCP2" = "1" && test "$OPENSSL_ENABLED" = "1" && test "$OPENSSL_IS_BORINGSSL" = "1"; then + dnl backup the pre-ngtcp2_crypto_boringssl variables CLEANLDFLAGS="$LDFLAGS" CLEANLDFLAGSPC="$LDFLAGSPC" @@ -3442,7 +3456,7 @@ if test "x$USE_NGTCP2" = "x1" -a "x$OPENSSL_ENABLED" = "x1" -a "x$OPENSSL_IS_BOR CPPFLAGS="$CPPFLAGS $CPP_NGTCP2_CRYPTO_BORINGSSL" LIBS="$LIB_NGTCP2_CRYPTO_BORINGSSL $LIBS" - if test "x$cross_compiling" != "xyes"; then + if test "$cross_compiling" != "yes"; 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, @@ -3464,7 +3478,7 @@ if test "x$USE_NGTCP2" = "x1" -a "x$OPENSSL_ENABLED" = "x1" -a "x$OPENSSL_IS_BOR else dnl no ngtcp2_crypto_boringssl pkg-config found, deal with it - if test X"$want_tcp2" != Xdefault; then + if test "$want_tcp2" != "default"; 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.]) @@ -3472,7 +3486,7 @@ if test "x$USE_NGTCP2" = "x1" -a "x$OPENSSL_ENABLED" = "x1" -a "x$OPENSSL_IS_BOR fi fi -if test "x$USE_NGTCP2" = "x1" -a "x$GNUTLS_ENABLED" = "x1"; then +if test "$USE_NGTCP2" = "1" && test "$GNUTLS_ENABLED" = "1"; then dnl backup the pre-ngtcp2_crypto_gnutls variables CLEANLDFLAGS="$LDFLAGS" CLEANLDFLAGSPC="$LDFLAGSPC" @@ -3499,7 +3513,7 @@ if test "x$USE_NGTCP2" = "x1" -a "x$GNUTLS_ENABLED" = "x1"; then CPPFLAGS="$CPPFLAGS $CPP_NGTCP2_CRYPTO_GNUTLS" LIBS="$LIB_NGTCP2_CRYPTO_GNUTLS $LIBS" - if test "x$cross_compiling" != "xyes"; then + if test "$cross_compiling" != "yes"; then DIR_NGTCP2_CRYPTO_GNUTLS=`echo $LD_NGTCP2_CRYPTO_GNUTLS | $SED -e 's/^-L//'` fi AC_CHECK_LIB(ngtcp2_crypto_gnutls, ngtcp2_crypto_recv_client_initial_cb, @@ -3521,7 +3535,7 @@ if test "x$USE_NGTCP2" = "x1" -a "x$GNUTLS_ENABLED" = "x1"; then else dnl no ngtcp2_crypto_gnutls pkg-config found, deal with it - if test X"$want_tcp2" != Xdefault; then + if test "$want_tcp2" != "default"; 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_gnutls pkg-config file.]) @@ -3529,7 +3543,7 @@ if test "x$USE_NGTCP2" = "x1" -a "x$GNUTLS_ENABLED" = "x1"; then fi fi -if test "x$USE_NGTCP2" = "x1" -a "x$WOLFSSL_ENABLED" = "x1"; then +if test "$USE_NGTCP2" = "1" && test "$WOLFSSL_ENABLED" = "1"; then dnl backup the pre-ngtcp2_crypto_wolfssl variables CLEANLDFLAGS="$LDFLAGS" CLEANLDFLAGSPC="$LDFLAGSPC" @@ -3556,7 +3570,7 @@ if test "x$USE_NGTCP2" = "x1" -a "x$WOLFSSL_ENABLED" = "x1"; then CPPFLAGS="$CPPFLAGS $CPP_NGTCP2_CRYPTO_WOLFSSL" LIBS="$LIB_NGTCP2_CRYPTO_WOLFSSL $LIBS" - if test "x$cross_compiling" != "xyes"; then + if test "$cross_compiling" != "yes"; then DIR_NGTCP2_CRYPTO_WOLFSSL=`echo $LD_NGTCP2_CRYPTO_WOLFSSL | $SED -e 's/^-L//'` fi AC_CHECK_LIB(ngtcp2_crypto_wolfssl, ngtcp2_crypto_recv_client_initial_cb, @@ -3578,7 +3592,7 @@ if test "x$USE_NGTCP2" = "x1" -a "x$WOLFSSL_ENABLED" = "x1"; then else dnl no ngtcp2_crypto_wolfssl pkg-config found, deal with it - if test X"$want_tcp2" != Xdefault; then + if test "$want_tcp2" != "default"; 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_wolfssl pkg-config file.]) @@ -3592,7 +3606,7 @@ dnl ********************************************************************** OPT_OPENSSL_QUIC="no" -if test "x$disable_http" = "xyes" -o "x$OPENSSL_ENABLED" != "x1"; then +if test "$disable_http" = "yes" || test "$OPENSSL_ENABLED" != "1"; then # without HTTP or without openssl, no use OPT_OPENSSL_QUIC="no" fi @@ -3613,12 +3627,12 @@ case "$OPT_OPENSSL_QUIC" in esac curl_openssl_quic_msg="no (--with-openssl-quic)" -if test "x$want_openssl_quic" = "xyes"; then +if test "$want_openssl_quic" = "yes"; then - if test "$USE_NGTCP2" = 1; then + if test "$USE_NGTCP2" = "1"; then AC_MSG_ERROR([--with-openssl-quic and --with-ngtcp2 are mutually exclusive]) fi - if test "$have_openssl_quic" != 1; then + if test "$have_openssl_quic" != "1"; then AC_MSG_ERROR([--with-openssl-quic requires quic support and OpenSSL >= 3.3.0]) fi AC_DEFINE(USE_OPENSSL_QUIC, 1, [if openssl QUIC is in use]) @@ -3631,7 +3645,7 @@ dnl ********************************************************************** OPT_NGHTTP3="yes" -if test "x$USE_NGTCP2" != "x1" -a "x$USE_OPENSSL_QUIC" != "x1"; then +if test "$USE_NGTCP2" != "1" && test "$USE_OPENSSL_QUIC" != "1"; then # without ngtcp2 or openssl quic, nghttp3 is of no use for us OPT_NGHTTP3="no" want_nghttp3="no" @@ -3659,9 +3673,9 @@ case "$OPT_NGHTTP3" in esac curl_http3_msg="no (--with-nghttp3)" -if test X"$want_nghttp3" != Xno; then +if test "$want_nghttp3" != "no"; then - if test "x$USE_NGTCP2" != "x1" -a "x$USE_OPENSSL_QUIC" != "x1"; then + if test "$USE_NGTCP2" != "1" && test "$USE_OPENSSL_QUIC" != "1"; then # without ngtcp2 or openssl quic, nghttp3 is of no use for us AC_MSG_ERROR([nghttp3 enabled without a QUIC library; enable ngtcp2 or OpenSSL-QUIC]) fi @@ -3692,7 +3706,7 @@ if test X"$want_nghttp3" != Xno; then CPPFLAGS="$CPPFLAGS $CPP_NGHTTP3" LIBS="$LIB_NGHTTP3 $LIBS" - if test "x$cross_compiling" != "xyes"; then + if test "$cross_compiling" != "yes"; then DIR_NGHTTP3=`echo $LD_NGHTTP3 | $SED -e 's/^-L//'` fi AC_CHECK_LIB(nghttp3, nghttp3_conn_client_new_versioned, @@ -3712,10 +3726,9 @@ if test X"$want_nghttp3" != Xno; then CPPFLAGS=$CLEANCPPFLAGS LIBS=$CLEANLIBS ) - else dnl no nghttp3 pkg-config found, deal with it - if test X"$want_nghttp3" != Xdefault; then + if test "$want_nghttp3" != "default"; then dnl To avoid link errors, we do not allow --with-nghttp3 without dnl a pkgconfig file AC_MSG_ERROR([--with-nghttp3 was specified but could not find nghttp3 pkg-config file.]) @@ -3727,7 +3740,7 @@ dnl ********************************************************************** dnl Check for ngtcp2 and nghttp3 (HTTP/3 with ngtcp2 + nghttp3) dnl ********************************************************************** -if test "x$USE_NGTCP2" = "x1" -a "x$USE_NGHTTP3" = "x1"; then +if test "$USE_NGTCP2" = "1" && test "$USE_NGHTTP3" = "1"; then USE_NGTCP2_H3=1 AC_MSG_NOTICE([HTTP3 support is experimental]) curl_h3_msg="enabled (ngtcp2 + nghttp3)" @@ -3737,7 +3750,7 @@ 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 +if test "$USE_OPENSSL_QUIC" = "1" && test "$USE_NGHTTP3" = "1"; then experimental="$experimental HTTP3" USE_OPENSSL_H3=1 AC_MSG_NOTICE([HTTP3 support is experimental]) @@ -3750,7 +3763,7 @@ dnl ********************************************************************** OPT_QUICHE="no" -if test "x$disable_http" = "xyes" -o "x$USE_NGTCP" = "x1"; then +if test "$disable_http" = "yes" || test "$USE_NGTCP" = "1"; then # without HTTP or with ngtcp2, quiche is no use OPT_QUICHE="no" fi @@ -3776,13 +3789,13 @@ case "$OPT_QUICHE" in ;; esac -if test X"$want_quiche" != Xno; then +if test "$want_quiche" != "no"; 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 + if test "$NGHTTP3_ENABLED" = "1"; then AC_MSG_ERROR([--with-quiche and --with-ngtcp2 are mutually exclusive]) fi @@ -3812,7 +3825,7 @@ if test X"$want_quiche" != Xno; then CPPFLAGS="$CPPFLAGS $CPP_QUICHE" LIBS="$LIB_QUICHE $LIBS" - if test "x$cross_compiling" != "xyes"; then + if test "$cross_compiling" != "yes"; then DIR_QUICHE=`echo $LD_QUICHE | $SED -e 's/^-L//'` fi AC_CHECK_LIB(quiche, quiche_conn_send_ack_eliciting, @@ -3836,11 +3849,11 @@ if test X"$want_quiche" != Xno; then ) ], dnl not found, revert back to clean variables - AC_MSG_ERROR([couldn't use quiche]) + AC_MSG_ERROR([could not use quiche]) ) else dnl no quiche pkg-config found, deal with it - if test X"$want_quiche" != Xdefault; then + if test "$want_quiche" != "default"; then dnl To avoid link errors, we do not allow --with-quiche without dnl a pkgconfig file AC_MSG_ERROR([--with-quiche was specified but could not find quiche pkg-config file.]) @@ -3874,8 +3887,8 @@ case "$OPT_LIBUV" in ;; esac -if test X"$want_libuv" != Xno; then - if test x$want_debug != xyes; then +if test "$want_libuv" != "no"; then + if test "$want_debug" != "yes"; then AC_MSG_ERROR([Using libuv without debug support enabled is useless]) fi @@ -3905,7 +3918,7 @@ if test X"$want_libuv" != Xno; then CPPFLAGS="$CPPFLAGS $CPP_LIBUV" LIBS="$LIB_LIBUV $LIBS" - if test "x$cross_compiling" != "xyes"; then + if test "$cross_compiling" != "yes"; then DIR_LIBUV=`echo $LD_LIBUV | $SED -e 's/^-L//'` fi AC_CHECK_LIB(uv, uv_default_loop, @@ -3925,10 +3938,9 @@ if test X"$want_libuv" != Xno; then CPPFLAGS=$CLEANCPPFLAGS LIBS=$CLEANLIBS ) - else dnl no libuv pkg-config found, deal with it - if test X"$want_libuv" != Xdefault; then + if test "$want_libuv" != "default"; then dnl To avoid link errors, we do not allow --with-libuv without dnl a pkgconfig file AC_MSG_ERROR([--with-libuv was specified but could not find libuv pkg-config file.]) @@ -3961,11 +3973,11 @@ case "$OPT_ZSH_FPATH" in AC_SUBST(ZSH_FUNCTIONS_DIR) ;; esac -if test -z "$PERL" -a x"$ZSH_FUNCTIONS_DIR" != x; then +if test -z "$PERL" && test -n "$ZSH_FUNCTIONS_DIR"; then AC_MSG_WARN([perl was not found. Will not install zsh completions.]) ZSH_FUNCTIONS_DIR='' fi -AM_CONDITIONAL(USE_ZSH_COMPLETION, test x"$ZSH_FUNCTIONS_DIR" != x) +AM_CONDITIONAL(USE_ZSH_COMPLETION, test -n "$ZSH_FUNCTIONS_DIR") dnl ********************************************************************** dnl Check for fish completion path @@ -3996,13 +4008,13 @@ case "$OPT_FISH_FPATH" in AC_SUBST(FISH_FUNCTIONS_DIR) ;; esac -if test -z "$PERL" -a x"$FISH_FUNCTIONS_DIR" != x; then +if test -z "$PERL" && test -n "$FISH_FUNCTIONS_DIR"; then AC_MSG_WARN([perl was not found. Will not install fish completions.]) FISH_FUNCTIONS_DIR='' fi -AM_CONDITIONAL(USE_FISH_COMPLETION, test x"$FISH_FUNCTIONS_DIR" != x) +AM_CONDITIONAL(USE_FISH_COMPLETION, test -n "$FISH_FUNCTIONS_DIR") -dnl Now check for the very most basic headers. Then we can use these +dnl Now check for the most basic headers. Then we can use these dnl ones as default-headers when checking for the rest! AC_CHECK_HEADERS( sys/types.h \ @@ -4069,7 +4081,6 @@ dnl default includes ] ) - dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_TYPE_SIZE_T @@ -4096,11 +4107,10 @@ CPPFLAGS=$o AC_CHECK_TYPE(long long, [AC_DEFINE(HAVE_LONGLONG, 1, [Define to 1 if the compiler supports the 'long long' data type.])] - longlong="yes" ) -if test ${ac_cv_sizeof_curl_off_t} -lt 8; then - AC_MSG_ERROR([64 bit curl_off_t is required]) +if test "$ac_cv_sizeof_curl_off_t" -lt 8; then + AC_MSG_ERROR([64-bit curl_off_t is required]) fi # check for ssize_t @@ -4120,7 +4130,7 @@ AC_CHECK_TYPE([bool],[ #endif ]) -if test "$curl_cv_native_windows" != 'yes'; then +if test "$curl_cv_native_windows" != "yes"; then # check for sa_family_t AC_CHECK_TYPE(sa_family_t, AC_DEFINE(HAVE_SA_FAMILY_T, 1, [Define to 1 if symbol `sa_family_t' exists]),, @@ -4193,6 +4203,7 @@ CURL_CHECK_FUNC_GMTIME_R CURL_CHECK_FUNC_IOCTL CURL_CHECK_FUNC_IOCTLSOCKET CURL_CHECK_FUNC_IOCTLSOCKET_CAMEL +CURL_CHECK_FUNC_LOCALTIME_R CURL_CHECK_FUNC_MEMRCHR CURL_CHECK_FUNC_SIGACTION CURL_CHECK_FUNC_SIGINTERRUPT @@ -4235,7 +4246,7 @@ AC_CHECK_FUNCS([\ utimes \ ]) -if test "$curl_cv_native_windows" = 'yes'; then +if test "$curl_cv_native_windows" = "yes"; then AC_MSG_CHECKING([for if_nametoindex on Windows]) AC_LINK_IFELSE([ AC_LANG_PROGRAM([[ @@ -4267,18 +4278,16 @@ else CURL_CHECK_FUNC_STRICMP fi -if test "$curl_cv_wince" = 'no'; then - AC_CHECK_FUNCS([setmode]) - if test "$curl_cv_native_windows" = 'yes' -o "$curl_cv_cygwin" = 'yes'; then - AC_CHECK_FUNCS([_setmode]) - fi +AC_CHECK_FUNCS([setmode]) +if test "$curl_cv_native_windows" = "yes" || test "$curl_cv_cygwin" = "yes"; then + AC_CHECK_FUNCS([_setmode]) fi if test -z "$ssl_backends"; then AC_CHECK_FUNCS([arc4random]) fi -if test "$curl_cv_native_windows" != 'yes'; then +if test "$curl_cv_native_windows" != "yes"; then AC_CHECK_FUNCS([fseeko]) dnl On Android, the only way to know if fseeko can be used is to see if it is @@ -4294,7 +4303,7 @@ fi CURL_CHECK_NONBLOCKING_SOCKET dnl set variable for use in automakefile(s) -AM_CONDITIONAL(BUILD_DOCS, test x"$BUILD_DOCS" = x1) +AM_CONDITIONAL(BUILD_DOCS, test "$BUILD_DOCS" = "1") dnl ************************************************************************* dnl If the manual variable still is set, then we go with providing a built-in @@ -4305,12 +4314,12 @@ if test "$USE_MANUAL" = "1"; then fi dnl set variable for use in automakefile(s) -AM_CONDITIONAL(USE_MANUAL, test x"$USE_MANUAL" = x1) +AM_CONDITIONAL(USE_MANUAL, test "$USE_MANUAL" = "1") CURL_CHECK_LIB_ARES CURL_CHECK_OPTION_THREADED_RESOLVER -if test "$ipv6" = yes -a "$curl_cv_apple" = 'yes'; then +if test "$ipv6" = "yes" && test "$curl_cv_apple" = "yes"; then CURL_DARWIN_SYSTEMCONFIGURATION fi @@ -4346,7 +4355,7 @@ if test "$want_threaded_resolver" = "yes" && test "$USE_THREADS_WIN32" != "1"; t ;; esac - dnl if it wasn't found without lib, search for it in pthread lib + dnl if it was not found without lib, search for it in pthread lib if test "$USE_THREADS_POSIX" != "1"; then # assign PTHREAD for pkg-config use PTHREAD=" -pthread" @@ -4355,7 +4364,7 @@ if test "$want_threaded_resolver" = "yes" && test "$USE_THREADS_WIN32" != "1"; t *-ibm-aix*) dnl Check if compiler is xlC COMPILER_VERSION=`"$CC" -qversion 2>/dev/null` - if test x"$COMPILER_VERSION" = "x"; then + if test -z "$COMPILER_VERSION"; then CFLAGS="$CFLAGS -pthread" else CFLAGS="$CFLAGS -qthreaded" @@ -4374,7 +4383,7 @@ if test "$want_threaded_resolver" = "yes" && test "$USE_THREADS_WIN32" != "1"; t [ CFLAGS="$save_CFLAGS"]) fi - if test "x$USE_THREADS_POSIX" = "x1"; then + if test "$USE_THREADS_POSIX" = "1"; then AC_DEFINE(USE_THREADS_POSIX, 1, [if you want POSIX threaded DNS lookup]) curl_res_msg="POSIX threaded" fi @@ -4382,7 +4391,7 @@ if test "$want_threaded_resolver" = "yes" && test "$USE_THREADS_WIN32" != "1"; t fi dnl Did we find a threading option? -if test "$want_threaded_resolver" != "no" -a "x$USE_THREADS_POSIX" != "x1" -a "x$USE_THREADS_WIN32" != "x1"; then +if test "$want_threaded_resolver" != "no" && test "$USE_THREADS_POSIX" != "1" && test "$USE_THREADS_WIN32" != "1"; then AC_MSG_ERROR([Threaded resolver enabled but no thread library found]) fi @@ -4394,6 +4403,26 @@ AC_CHECK_HEADER(dirent.h, CURL_CONVERT_INCLUDE_TO_ISYSTEM +dnl ************************************************************ +dnl disable curl_easy_setopt()/curl_easy_getinfo() type checking +dnl +AC_MSG_CHECKING([whether to enable curl_easy_setopt()/curl_easy_getinfo() type checking]) +AC_ARG_ENABLE(typecheck, +AS_HELP_STRING([--enable-typecheck],[Enable type checking (default)]) +AS_HELP_STRING([--disable-typecheck],[Disable type checking]), +[ case "$enableval" in + no) + AC_MSG_RESULT(no) + AC_DEFINE(CURL_DISABLE_TYPECHECK, 1, [to disable type checking]) + curl_typecheck_msg="no" + ;; + *) + AC_MSG_RESULT(yes) + ;; + esac ], + AC_MSG_RESULT(yes) +) + dnl ************************************************************ dnl disable verbose text strings dnl @@ -4414,7 +4443,7 @@ AS_HELP_STRING([--disable-verbose],[Disable verbose strings]), AC_MSG_RESULT(yes) ) -if test "$curl_cv_winuwp" != 'yes'; then +if test "$curl_cv_winuwp" != "yes"; then dnl ************************************************************ dnl enable SSPI support dnl @@ -4435,7 +4464,7 @@ if test "$curl_cv_winuwp" != 'yes'; then fi ;; *) - if test "x$SCHANNEL_ENABLED" = "x1"; then + if test "$SCHANNEL_ENABLED" = "1"; then # --with-schannel implies --enable-sspi AC_MSG_RESULT(yes) else @@ -4443,7 +4472,7 @@ if test "$curl_cv_winuwp" != 'yes'; then fi ;; esac ], - if test "x$SCHANNEL_ENABLED" = "x1"; then + if test "$SCHANNEL_ENABLED" = "1"; then # --with-schannel implies --enable-sspi AC_MSG_RESULT(yes) else @@ -4451,7 +4480,7 @@ if test "$curl_cv_winuwp" != 'yes'; then fi ) - if test "x$USE_WINDOWS_SSPI" = "x1"; then + if test "$USE_WINDOWS_SSPI" = "1"; then LIBS="-lsecur32 $LIBS" fi fi @@ -4613,7 +4642,7 @@ AS_HELP_STRING([--disable-tls-srp],[Disable TLS-SRP authentication]), want_tls_srp=yes ) -if test "$want_tls_srp" = "yes" && ( test "x$HAVE_GNUTLS_SRP" = "x1" || test "x$HAVE_OPENSSL_SRP" = "x1"); then +if test "$want_tls_srp" = "yes" && (test "$HAVE_GNUTLS_SRP" = "1" || test "$HAVE_OPENSSL_SRP" = "1"); then AC_DEFINE(USE_TLS_SRP, 1, [Use TLS-SRP authentication]) USE_TLS_SRP=1 curl_tls_srp_msg="enabled" @@ -4640,8 +4669,8 @@ AS_HELP_STRING([--disable-unix-sockets],[Disable Unix domain sockets]), want_unix_sockets=auto ] ) -if test "x$want_unix_sockets" != "xno" -a "$curl_cv_wince" = 'no'; then - if test "x$curl_cv_native_windows" = "xyes"; then +if test "$want_unix_sockets" != "no"; then + if test "$curl_cv_native_windows" = "yes"; then USE_UNIX_SOCKETS=1 AC_DEFINE(USE_UNIX_SOCKETS, 1, [Use Unix domain sockets]) curl_unix_sockets_msg="enabled" @@ -4651,7 +4680,7 @@ if test "x$want_unix_sockets" != "xno" -a "$curl_cv_wince" = 'no'; then USE_UNIX_SOCKETS=1 curl_unix_sockets_msg="enabled" ], [ - if test "x$want_unix_sockets" = "xyes"; then + if test "$want_unix_sockets" = "yes"; then AC_MSG_ERROR([--enable-unix-sockets is not available on this platform!]) fi ], [ @@ -4788,12 +4817,12 @@ AS_HELP_STRING([--disable-form-api],[Disable form API support]), ;; *) AC_MSG_RESULT(yes) - test "$enable_mime" = no && + test "x$enable_mime" = "xno" && AC_MSG_ERROR(MIME support needs to be enabled in order to enable form API support) ;; esac ], [ - if test "$enable_mime" = no; then + if test "x$enable_mime" = "xno"; then enable_form_api=no AC_MSG_RESULT(no) AC_DEFINE(CURL_DISABLE_FORM_API, 1, [disable form API]) @@ -4957,7 +4986,7 @@ AS_HELP_STRING([--disable-headers-api],[Disable headers-api support]), AC_MSG_RESULT(yes) ) -dnl only check for HSTS if there's SSL present +dnl only check for HSTS if there is SSL present if test -n "$SSL_ENABLED"; then dnl ************************************************************ dnl switch on/off hsts @@ -4982,16 +5011,15 @@ else hsts="no" fi -if test "x$hsts" != "xyes"; then +if test "$hsts" != "yes"; then curl_hsts_msg="no (--enable-hsts)"; AC_DEFINE(CURL_DISABLE_HSTS, 1, [disable alt-svc]) fi - dnl ************************************************************* dnl check whether ECH support, if desired, is actually available dnl -if test "x$want_ech" != "xno"; then +if test "$want_ech" != "no"; then AC_MSG_CHECKING([whether ECH support is available]) dnl assume NOT and look for sufficient condition @@ -5002,25 +5030,25 @@ if test "x$want_ech" != "xno"; then ECH_SUPPORT='' dnl check for OpenSSL equivalent - if test "x$OPENSSL_ENABLED" = "x1"; then + if test "$OPENSSL_ENABLED" = "1"; then AC_CHECK_FUNCS(SSL_set1_ech_config_list, ECH_SUPPORT="$ECH_SUPPORT OpenSSL" ECH_ENABLED_OPENSSL=1) fi - if test "x$WOLFSSL_ENABLED" = "x1"; then + if test "$WOLFSSL_ENABLED" = "1"; then AC_CHECK_FUNCS(wolfSSL_CTX_GenerateEchConfig, ECH_SUPPORT="$ECH_SUPPORT wolfSSL" ECH_ENABLED_WOLFSSL=1) fi - if test "x$RUSTLS_ENABLED" = "x1"; then + if test "$RUSTLS_ENABLED" = "1"; then ECH_SUPPORT="$ECH_SUPPORT rustls-ffi" ECH_ENABLED_RUSTLS=1 fi dnl now deal with whatever we found - if test "x$ECH_ENABLED_OPENSSL" = "x1" -o \ - "x$ECH_ENABLED_WOLFSSL" = "x1" -o \ - "x$ECH_ENABLED_RUSTLS" = "x1"; then + if test "$ECH_ENABLED_OPENSSL" = "1" || + test "$ECH_ENABLED_WOLFSSL" = "1" || + test "$ECH_ENABLED_RUSTLS" = "1"; then AC_DEFINE(USE_ECH, 1, [if ECH support is available]) AC_MSG_RESULT(ECH support available via:$ECH_SUPPORT) experimental="$experimental ECH" @@ -5036,7 +5064,7 @@ AC_MSG_CHECKING([whether to enable HTTPS-RR support]) dnl ************************************************************* dnl check whether HTTPSRR support if desired dnl -if test "x$want_httpsrr" != "xno"; then +if test "$want_httpsrr" != "no"; then AC_MSG_RESULT([yes]) AC_DEFINE(USE_HTTPSRR, 1, [enable HTTPS RR support]) experimental="$experimental HTTPSRR" @@ -5046,21 +5074,20 @@ else # no HTTPSRR wanted if test "$want_threaded_resolver" = "yes"; then # and using the threaded resolver - if test "x$USE_ARES" = "x1"; then + if test "$USE_ARES" = "1"; then AC_MSG_ERROR([without HTTPS-RR support, asking for both threaded resolver and c-ares support is ambivalent. Please drop one of them.]) fi fi fi - dnl ************************************************************* dnl check whether OpenSSL (lookalikes) have SSL_set0_wbio dnl -if test "x$OPENSSL_ENABLED" = "x1"; then +if test "$OPENSSL_ENABLED" = "1"; then AC_CHECK_FUNCS([SSL_set0_wbio]) fi -if test "x$CURL_DISABLE_HTTP" != "x1"; then +if test "$CURL_DISABLE_HTTP" != "1"; then dnl ************************************************************* dnl WebSockets dnl @@ -5075,12 +5102,12 @@ if test "x$CURL_DISABLE_HTTP" != "x1"; then CURL_DISABLE_WEBSOCKETS=1 ;; *) - if test ${ac_cv_sizeof_curl_off_t} -gt 4; then + if test "$ac_cv_sizeof_curl_off_t" -gt 4; then AC_MSG_RESULT(yes) else - dnl WebSockets requires >32 bit curl_off_t + dnl WebSockets requires >32-bit curl_off_t AC_MSG_RESULT(no) - AC_MSG_WARN([WebSockets disabled due to lack of >32 bit curl_off_t]) + AC_MSG_WARN([WebSockets disabled due to lack of >32-bit curl_off_t]) AC_DEFINE(CURL_DISABLE_WEBSOCKETS, [1], [disable WebSockets]) CURL_DISABLE_WEBSOCKETS=1 fi @@ -5097,14 +5124,14 @@ fi dnl ************************************************************* dnl check whether experimental SSL Session Im-/Export is enabled dnl -if test "x$want_ssls_export" != "xno"; then +if test "$want_ssls_export" != "no"; then AC_MSG_CHECKING([whether SSL session export support is available]) dnl assume NOT and look for sufficient condition SSLS_EXPORT_ENABLED=0 SSLS_EXPORT_SUPPORT='' - if test "x$SSL_ENABLED" != "x1"; then + if test "$SSL_ENABLED" != "1"; then AC_MSG_WARN([--enable-ssls-export ignored: No SSL support]) else SSLS_EXPORT_ENABLED=1 @@ -5153,7 +5180,7 @@ dnl all link targets in given makefile. BLANK_AT_MAKETIME= AC_SUBST(BLANK_AT_MAKETIME) -AM_CONDITIONAL(CROSSCOMPILING, test x$cross_compiling = xyes) +AM_CONDITIONAL(CROSSCOMPILING, test "$cross_compiling" = "yes") dnl yes or no ENABLE_SHARED="$enable_shared" @@ -5169,7 +5196,7 @@ LIBCURL_PC_REQUIRES_PRIVATE=`echo $LIBCURL_PC_REQUIRES_PRIVATE | tr ' ' ','` AC_SUBST(LIBCURL_PC_REQUIRES_PRIVATE) dnl Merge pkg-config private fields into public ones when static-only -if test "x$enable_shared" = "xno"; then +if test "$enable_shared" = "no"; then LIBCURL_PC_REQUIRES=$LIBCURL_PC_REQUIRES_PRIVATE LIBCURL_PC_LIBS=$LIBCURL_PC_LIBS_PRIVATE else @@ -5186,118 +5213,117 @@ dnl For keeping supported features and protocols also in pkg-config file dnl since it is more cross-compile friendly than curl-config dnl -if test "x$OPENSSL_ENABLED" = "x1"; then +if test "$OPENSSL_ENABLED" = "1"; then SUPPORT_FEATURES="$SUPPORT_FEATURES SSL" elif test -n "$SSL_ENABLED"; then SUPPORT_FEATURES="$SUPPORT_FEATURES SSL" fi -if test "x$IPV6_ENABLED" = "x1"; then +if test "$IPV6_ENABLED" = "1"; then SUPPORT_FEATURES="$SUPPORT_FEATURES IPv6" fi -if test "x$USE_UNIX_SOCKETS" = "x1"; then +if test "$USE_UNIX_SOCKETS" = "1"; then SUPPORT_FEATURES="$SUPPORT_FEATURES UnixSockets" fi -if test "x$HAVE_LIBZ" = "x1"; then +if test "$HAVE_LIBZ" = "1"; then SUPPORT_FEATURES="$SUPPORT_FEATURES libz" fi -if test "x$HAVE_BROTLI" = "x1"; then +if test "$HAVE_BROTLI" = "1"; then SUPPORT_FEATURES="$SUPPORT_FEATURES brotli" fi -if test "x$HAVE_ZSTD" = "x1"; then +if test "$HAVE_ZSTD" = "1"; then SUPPORT_FEATURES="$SUPPORT_FEATURES zstd" fi -if test "x$USE_ARES" = "x1" -o "x$USE_THREADS_POSIX" = "x1" \ - -o "x$USE_THREADS_WIN32" = "x1"; then +if test "$USE_ARES" = "1" || test "$USE_THREADS_POSIX" = "1" || test "$USE_THREADS_WIN32" = "1"; then SUPPORT_FEATURES="$SUPPORT_FEATURES AsynchDNS" fi -if test "x$USE_ARES" = "x1" -a "$want_threaded_resolver" = "yes" -a "x$want_httpsrr" != "xno"; then +if test "$USE_ARES" = "1" && test "$want_threaded_resolver" = "yes" && test "$want_httpsrr" != "no"; then SUPPORT_FEATURES="$SUPPORT_FEATURES asyn-rr" fi -if test "x$IDN_ENABLED" = "x1"; then +if test "$IDN_ENABLED" = "1"; then SUPPORT_FEATURES="$SUPPORT_FEATURES IDN" fi -if test "x$USE_WINDOWS_SSPI" = "x1"; then +if test "$USE_WINDOWS_SSPI" = "1"; then SUPPORT_FEATURES="$SUPPORT_FEATURES SSPI" fi -if test "x$HAVE_GSSAPI" = "x1"; then +if test "$HAVE_GSSAPI" = "1"; then SUPPORT_FEATURES="$SUPPORT_FEATURES GSS-API" fi -if test "x$curl_psl_msg" = "xenabled"; then +if test "$curl_psl_msg" = "enabled"; then SUPPORT_FEATURES="$SUPPORT_FEATURES PSL" fi -if test "x$curl_gsasl_msg" = "xenabled"; then +if test "$curl_gsasl_msg" = "enabled"; then SUPPORT_FEATURES="$SUPPORT_FEATURES gsasl" fi -if test "x$enable_altsvc" = "xyes"; then +if test "$enable_altsvc" = "yes"; then SUPPORT_FEATURES="$SUPPORT_FEATURES alt-svc" fi -if test "x$hsts" = "xyes"; then +if test "$hsts" = "yes"; then SUPPORT_FEATURES="$SUPPORT_FEATURES HSTS" fi -if test "x$CURL_DISABLE_NEGOTIATE_AUTH" != "x1" -a \ - \( "x$HAVE_GSSAPI" = "x1" -o "x$USE_WINDOWS_SSPI" = "x1" \); then +if test "$CURL_DISABLE_NEGOTIATE_AUTH" != "1" && (test "$HAVE_GSSAPI" = "1" || test "$USE_WINDOWS_SSPI" = "1"); then SUPPORT_FEATURES="$SUPPORT_FEATURES SPNEGO" fi -if test "x$CURL_DISABLE_KERBEROS_AUTH" != "x1" -a \ - \( "x$HAVE_GSSAPI" = "x1" -o "x$USE_WINDOWS_SSPI" = "x1" \); then +if test "$CURL_DISABLE_KERBEROS_AUTH" != "1" && (test "$HAVE_GSSAPI" = "1" || test "$USE_WINDOWS_SSPI" = "1"); then SUPPORT_FEATURES="$SUPPORT_FEATURES Kerberos" fi use_curl_ntlm_core=no -if test "x$CURL_DISABLE_NTLM" != "x1"; then - if test "x$OPENSSL_ENABLED" = "x1" -o "x$MBEDTLS_ENABLED" = "x1" \ - -o "x$GNUTLS_ENABLED" = "x1" \ - -o "x$USE_WIN32_CRYPTO" = "x1" \ - -o "x$HAVE_WOLFSSL_DES_ECB_ENCRYPT" = "x1"; then +if test "$CURL_DISABLE_NTLM" != "1"; then + if test "$HAVE_DES_ECB_ENCRYPT" = "1" || + test "$GNUTLS_ENABLED" = "1" || + test "$USE_WIN32_CRYPTO" = "1" || + test "$HAVE_WOLFSSL_DES_ECB_ENCRYPT" = "1" || + test "$HAVE_MBEDTLS_DES_CRYPT_ECB" = "1"; then use_curl_ntlm_core=yes fi - if test "x$use_curl_ntlm_core" = "xyes" \ - -o "x$USE_WINDOWS_SSPI" = "x1"; then + if test "$use_curl_ntlm_core" = "yes" || + test "$USE_WINDOWS_SSPI" = "1"; then SUPPORT_FEATURES="$SUPPORT_FEATURES NTLM" fi fi -if test "x$USE_TLS_SRP" = "x1"; then +if test "$USE_TLS_SRP" = "1"; then SUPPORT_FEATURES="$SUPPORT_FEATURES TLS-SRP" fi -if test "x$USE_NGHTTP2" = "x1"; then +if test "$USE_NGHTTP2" = "1"; then SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP2" fi -if test "x$USE_NGTCP2_H3" = "x1" -o "x$USE_QUICHE" = "x1" \ - -o "x$USE_OPENSSL_H3" = "x1"; then - if test "x$CURL_WITH_MULTI_SSL" = "x1"; then +if test "$USE_NGTCP2_H3" = "1" || + test "$USE_QUICHE" = "1" || + test "$USE_OPENSSL_H3" = "1"; then + if test "$CURL_WITH_MULTI_SSL" = "1"; then AC_MSG_ERROR([MultiSSL cannot be enabled with HTTP/3 and vice versa]) fi SUPPORT_FEATURES="$SUPPORT_FEATURES HTTP3" fi -if test "x$CURL_WITH_MULTI_SSL" = "x1"; then +if test "$CURL_WITH_MULTI_SSL" = "1"; 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$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$RUSTLS_ENABLED" = "x1" \ - -o "x$SCHANNEL_ENABLED" = "x1" \ - -o "x$GNUTLS_ENABLED" = "x1" \ - -o "x$MBEDTLS_ENABLED" = "x1"; then +if test "$CURL_DISABLE_HTTP" != "1"; then + if test "$https_proxy" != "no"; then + if test "$OPENSSL_ENABLED" = "1" || + test "$GNUTLS_ENABLED" = "1" || + test "$RUSTLS_ENABLED" = "1" || + test "$SCHANNEL_ENABLED" = "1" || + test "$GNUTLS_ENABLED" = "1" || + test "$MBEDTLS_ENABLED" = "1"; then SUPPORT_FEATURES="$SUPPORT_FEATURES HTTPS-proxy" AC_MSG_RESULT([yes]) - elif test "x$WOLFSSL_ENABLED" = "x1" -a "x$HAVE_WOLFSSL_BIO_NEW" = "x1"; then + elif test "$WOLFSSL_ENABLED" = "1" && test "$HAVE_WOLFSSL_BIO_NEW" = "1"; then SUPPORT_FEATURES="$SUPPORT_FEATURES HTTPS-proxy" AC_MSG_RESULT([yes]) else @@ -5310,35 +5336,34 @@ else AC_MSG_RESULT([no]) fi -if test "x$OPENSSL_ENABLED" = "x1" -o -n "$SSL_ENABLED"; then - if test "x$ECH_ENABLED" = "x1"; then +if test "$OPENSSL_ENABLED" = "1" || test -n "$SSL_ENABLED"; then + if test "$ECH_ENABLED" = "1"; then SUPPORT_FEATURES="$SUPPORT_FEATURES ECH" fi fi -if test "x$APPLE_SECTRUST_ENABLED" = "x1"; then +if test "$APPLE_SECTRUST_ENABLED" = "1"; then SUPPORT_FEATURES="$SUPPORT_FEATURES AppleSecTrust" fi -if test "x$want_httpsrr" != "xno"; then +if test "$want_httpsrr" != "no"; then SUPPORT_FEATURES="$SUPPORT_FEATURES HTTPSRR" fi -if test "x$SSLS_EXPORT_ENABLED" = "x1"; then +if test "$SSLS_EXPORT_ENABLED" = "1"; then SUPPORT_FEATURES="$SUPPORT_FEATURES SSLS-EXPORT" fi -if test ${ac_cv_sizeof_curl_off_t} -gt 4; then - if test ${ac_cv_sizeof_off_t} -gt 4 -o \ - "$curl_win32_file_api" = "win32_large_files"; then +if test "$ac_cv_sizeof_curl_off_t" -gt 4; then + if test "$ac_cv_sizeof_off_t" -gt 4 || + test "$curl_cv_native_windows" = "yes"; then SUPPORT_FEATURES="$SUPPORT_FEATURES Largefile" fi 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 +elif test "$USE_THREADS_POSIX" = "1" && test "$ac_cv_header_pthread_h" = "yes"; then SUPPORT_FEATURES="$SUPPORT_FEATURES threadsafe" else AC_COMPILE_IFELSE([ @@ -5355,16 +5380,16 @@ else ]) fi -if test "x$want_winuni" = "xyes"; then +if test "$want_winuni" = "yes"; then SUPPORT_FEATURES="$SUPPORT_FEATURES Unicode" fi -if test "x$want_debug" = "xyes"; then +if test "$want_debug" = "yes"; then SUPPORT_FEATURES="$SUPPORT_FEATURES Debug" fi -if test "x$want_curldebug" = "xyes"; then +if test "$want_curldebug" = "yes"; then SUPPORT_FEATURES="$SUPPORT_FEATURES TrackMemory" fi -if test "x$CURL_CA_EMBED" != "x"; then +if test -n "$CURL_CA_EMBED"; then SUPPORT_FEATURES="$SUPPORT_FEATURES CAcert" CURL_CA_EMBED_msg="$CURL_CA_EMBED" else @@ -5382,93 +5407,92 @@ fi AC_SUBST(SUPPORT_FEATURES) dnl For supported protocols in pkg-config file -if test "x$CURL_DISABLE_HTTP" != "x1"; then +if test "$CURL_DISABLE_HTTP" != "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS HTTP" - if test "x$SSL_ENABLED" = "x1"; then + if test "$SSL_ENABLED" = "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS HTTPS" fi fi -if test "x$CURL_DISABLE_FTP" != "x1"; then +if test "$CURL_DISABLE_FTP" != "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS FTP" - if test "x$SSL_ENABLED" = "x1"; then + if test "$SSL_ENABLED" = "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS FTPS" fi fi -if test "x$CURL_DISABLE_FILE" != "x1"; then +if test "$CURL_DISABLE_FILE" != "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS FILE" fi -if test "x$CURL_DISABLE_TELNET" != "x1"; then +if test "$CURL_DISABLE_TELNET" != "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS TELNET" fi -if test "x$CURL_DISABLE_LDAP" != "x1"; then +if test "$CURL_DISABLE_LDAP" != "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS LDAP" - if test "x$CURL_DISABLE_LDAPS" != "x1"; then - if (test "x$USE_OPENLDAP" = "x1" && test "x$SSL_ENABLED" = "x1") || - (test "x$USE_OPENLDAP" != "x1" && test "x$HAVE_LDAP_SSL" = "x1"); then + if test "$CURL_DISABLE_LDAPS" != "1"; then + if (test "$USE_OPENLDAP" = "1" && test "$SSL_ENABLED" = "1") || + (test "$USE_OPENLDAP" != "1" && test "$HAVE_LDAP_SSL" = "1"); then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS LDAPS" fi fi fi -if test "x$CURL_DISABLE_DICT" != "x1"; then +if test "$CURL_DISABLE_DICT" != "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS DICT" fi -if test "x$CURL_DISABLE_TFTP" != "x1"; then +if test "$CURL_DISABLE_TFTP" != "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS TFTP" fi -if test "x$CURL_DISABLE_GOPHER" != "x1"; then +if test "$CURL_DISABLE_GOPHER" != "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS GOPHER" - if test "x$SSL_ENABLED" = "x1"; then + if test "$SSL_ENABLED" = "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS GOPHERS" fi fi -if test "x$CURL_DISABLE_MQTT" != "x1"; then +if test "$CURL_DISABLE_MQTT" != "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS MQTT" fi -if test "x$CURL_DISABLE_POP3" != "x1"; then +if test "$CURL_DISABLE_POP3" != "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS POP3" - if test "x$SSL_ENABLED" = "x1"; then + if test "$SSL_ENABLED" = "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS POP3S" fi fi -if test "x$CURL_DISABLE_IMAP" != "x1"; then +if test "$CURL_DISABLE_IMAP" != "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS IMAP" - if test "x$SSL_ENABLED" = "x1"; then + if test "$SSL_ENABLED" = "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS IMAPS" fi fi -if test "x$CURL_DISABLE_SMB" != "x1" \ - -a "x$use_curl_ntlm_core" = "xyes"; then +if test "$CURL_DISABLE_SMB" != "1" && test "$use_curl_ntlm_core" = "yes"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SMB" - if test "x$SSL_ENABLED" = "x1"; then + if test "$SSL_ENABLED" = "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SMBS" fi fi -if test "x$CURL_DISABLE_SMTP" != "x1"; then +if test "$CURL_DISABLE_SMTP" != "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SMTP" - if test "x$SSL_ENABLED" = "x1"; then + if test "$SSL_ENABLED" = "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SMTPS" fi fi -if test "x$USE_LIBSSH2" = "x1"; then +if test "$USE_LIBSSH2" = "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SCP" SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SFTP" fi -if test "x$USE_LIBSSH" = "x1"; then +if test "$USE_LIBSSH" = "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SCP" SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SFTP" fi -if test "x$CURL_DISABLE_IPFS" != "x1"; then +if test "$CURL_DISABLE_IPFS" != "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS IPFS IPNS" fi -if test "x$CURL_DISABLE_RTSP" != "x1"; then +if test "$CURL_DISABLE_RTSP" != "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS RTSP" fi -if test "x$USE_LIBRTMP" = "x1"; then +if test "$USE_LIBRTMP" = "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS RTMP" fi -if test "x$CURL_DISABLE_WEBSOCKETS" != "x1"; then +if test "$CURL_DISABLE_WEBSOCKETS" != "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS WS" - if test "x$SSL_ENABLED" = "x1"; then + if test "$SSL_ENABLED" = "1"; then SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS WSS" fi fi @@ -5500,8 +5524,8 @@ XC_CHECK_BUILD_FLAGS SSL_BACKENDS=${ssl_backends} AC_SUBST(SSL_BACKENDS) -if test "x$want_curldebug_assumed" = "xyes" && - test "x$want_curldebug" = "xyes" && test "x$USE_ARES" = "x1"; then +if test "$want_curldebug_assumed" = "yes" && + test "$want_curldebug" = "yes" && test "$USE_ARES" = "1"; then ac_configure_args="$ac_configure_args --enable-curldebug" fi @@ -5569,6 +5593,7 @@ AC_MSG_NOTICE([Configured to build curl/libcurl: Build libcurl: Shared=${enable_shared}, Static=${enable_static} Built-in manual: ${curl_manual_msg} --libcurl option: ${curl_libcurl_msg} + Type checking: ${curl_typecheck_msg} Verbose errors: ${curl_verbose_msg} Code coverage: ${curl_coverage_msg} SSPI: ${curl_sspi_msg} diff --git a/curl-config.in b/curl-config.in index ce23519c3306..a1c81858753f 100644 --- a/curl-config.in +++ b/curl-config.in @@ -149,7 +149,7 @@ while test "$#" -gt 0; do ;; --libs) - if test "@libdir@" != '/usr/lib' -a "@libdir@" != '/usr/lib64'; then + if test "@libdir@" != '/usr/lib' && test "@libdir@" != '/usr/lib64'; then curllibdir="-L@libdir@ " else curllibdir='' diff --git a/docs/ALTSVC.md b/docs/ALTSVC.md index bcdf5650743b..24b961a3fb4a 100644 --- a/docs/ALTSVC.md +++ b/docs/ALTSVC.md @@ -35,7 +35,8 @@ space separated fields. 4. The ALPN id for the destination host 5. The hostname for the destination host 6. The port 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. +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) diff --git a/docs/BINDINGS.md b/docs/BINDINGS.md index a72482cf8dfd..56f0376b6415 100644 --- a/docs/BINDINGS.md +++ b/docs/BINDINGS.md @@ -49,7 +49,7 @@ Clojure: [clj-curl](https://github.com/lsevero/clj-curl) by Lucas Severo [Fortran](https://github.com/interkosmos/fortran-curl) Written by Philipp Engel -[Gambas](https://gambas.sourceforge.net/) +[Gambas](https://gambaswiki.org/website/en/main.html) [glib/GTK+](https://web.archive.org/web/20100526203452/atterer.net/glibcurl) Written by Richard Atterer @@ -61,7 +61,7 @@ Go: [go-curl](https://github.com/andelf/go-curl) by ShuYu Wang [Haskell](https://hackage.haskell.org/package/curl) Written by Galois, Inc -[Hollywood](https://www.hollywood-mal.com/download.html) hURL by Andreas Falkenhahn +[Hollywood](https://web.archive.org/web/20250116185836/www.hollywood-mal.com/download.html) hURL by Andreas Falkenhahn [Java](https://github.com/covers1624/curl4j) @@ -73,7 +73,7 @@ Go: [go-curl](https://github.com/andelf/go-curl) by ShuYu Wang [LibQurl](https://github.com/Qriist/LibQurl) a feature rich AutoHotKey v2 (AHKv2) wrapper around libcurl. -Lua: [luacurl](https://web.archive.org/web/20201205052437/luacurl.luaforge.net/) by Alexander Marinov, [Lua-cURL](https://github.com/Lua-cURL) by Jürgen Hötzel +Lua: [luacurl](https://web.archive.org/web/20201205052437/luacurl.luaforge.net/) by Alexander Marinov, [Lua-curl](https://github.com/Lua-cURL) by Jürgen Hötzel [Mono](https://web.archive.org/web/20070606064500/forge.novell.com/modules/xfmod/project/?libcurl-mono) Written by Jeffrey Phillips @@ -98,11 +98,11 @@ Bailiff and Bálint Szilakszi, [PostgreSQL](https://github.com/pramsey/pgsql-http) - HTTP client for PostgreSQL -[PostgreSQL](https://github.com/RekGRpth/pg_curl) - cURL client for PostgreSQL +[PostgreSQL](https://github.com/RekGRpth/pg_curl) - curl client for PostgreSQL -[PureBasic](https://www.purebasic.com/documentation/http/index.html) uses libcurl in its "native" HTTP subsystem +[PureBasic](https://web.archive.org/web/20250325015028/www.purebasic.com/documentation/http/index.html) uses libcurl in its "native" HTTP subsystem -[Python](http://pycurl.io/) PycURL by Kjetil Jacobsen +[Python](https://github.com/pycurl/pycurl) PycURL by Kjetil Jacobsen [Python](https://pypi.org/project/pymcurl/) mcurl by Ganesh Viswanathan @@ -112,7 +112,7 @@ Bailiff and Bálint Szilakszi, [Rexx](https://rexxcurl.sourceforge.net/) Written Mark Hessling -[Ring](https://ring-lang.sourceforge.io/doc1.3/libcurl.html) RingLibCurl by Mahmoud Fayed +[Ring](https://ring-lang.github.io/doc1.24/libcurl.html) RingLibCurl by Mahmoud Fayed RPG, support for ILE/RPG on OS/400 is included in source distribution diff --git a/docs/CONTRIBUTE.md b/docs/CONTRIBUTE.md index 710b3a1ef837..3abf729598a7 100644 --- a/docs/CONTRIBUTE.md +++ b/docs/CONTRIBUTE.md @@ -111,8 +111,8 @@ 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. -Documentation is mostly provided as manpages or plain ASCII files. The -manpages are rendered from their source files that are usually written using +Documentation is mostly provided as man pages or plain ASCII files. The +man pages are rendered from their source files that are usually written using markdown. Most HTML files on the website and in the release archives are generated from corresponding markdown and ASCII files. @@ -289,7 +289,7 @@ Just ask if this is what you would want. You are required to have posted several high quality patches first, before you can be granted push access. ## Useful resources - - [Webinar on getting code into cURL](https://www.youtube.com/watch?v=QmZ3W1d6LQI) + - [Webinar on getting code into curl](https://youtu.be/QmZ3W1d6LQI) # Update copyright and license information diff --git a/docs/CURL-DISABLE.md b/docs/CURL-DISABLE.md index 63de4026a6d2..c266f0c0adc9 100644 --- a/docs/CURL-DISABLE.md +++ b/docs/CURL-DISABLE.md @@ -68,8 +68,8 @@ Disable the FTP (and FTPS) protocol ## `CURL_DISABLE_GETOPTIONS` -Disable the `curl_easy_options` API calls that lets users get information -about existing options to `curl_easy_setopt`. +Disable the `curl_easy_options()` API calls that lets users get information +about existing options to `curl_easy_setopt()`. ## `CURL_DISABLE_GOPHER` @@ -182,6 +182,12 @@ Disable the TELNET protocol Disable the TFTP protocol +## `CURL_DISABLE_TYPECHECK` + +Disable `curl_easy_setopt()`/`curl_easy_getinfo()` type checking. + +Useful to improve build performance for the `tests/libtest` test tool. + ## `CURL_DISABLE_VERBOSE_STRINGS` Disable verbose strings and error messages. diff --git a/docs/DEPRECATE.md b/docs/DEPRECATE.md index 43c94875b175..2219bd32645e 100644 --- a/docs/DEPRECATE.md +++ b/docs/DEPRECATE.md @@ -12,24 +12,6 @@ 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. -## Windows CE - -Windows CE "mainstream support" ended on October 9, 2018, and "Extended -Support" ended on October 10, 2023. - -curl drops all support in November 2025. - -## VS2008 - -curl drops support for getting built with Microsoft Visual Studio 2008 in -November 2025. - -The only reason we kept support for this version is for Windows CE - and we -intend to remove support for that Operating System in this time frame as well. -Bumping the minimum to VS2010. VS2008 is a pain to support. - -Previous discussion and details: https://github.com/curl/curl/discussions/15972 - ## Windows XP In January 2026, curl drops support for Windows XP and Server 2003. Their @@ -41,20 +23,6 @@ Making the new minimum target Windows version Vista / Server 2008. In March 2026, we drop support for all c-ares versions before 1.16.0. -## OpenSSL 1.0.2 - -OpenSSL and others only ship fixes for this version to paying customers, -meaning users of the free version risk being vulnerable. - -We remove support for this OpenSSL version from curl in December 2025. - -## OpenSSL 1.1.1 - -OpenSSL and others only ship fixes to paying customers, meaning users of the -free version risk being vulnerable. - -We remove support for this OpenSSL version from curl in December 2025. - ## OpenSSL-QUIC OpenSSL-QUIC is what we call the curl QUIC backend that uses the OpenSSL QUIC @@ -68,7 +36,25 @@ stack. - curl users building with vanilla OpenSSL can still use QUIC through the means of ngtcp2 -We remove the OpenSSL-QUIC backend in March 2026. +We remove the OpenSSL-QUIC backend in January 2026. + +## RTMP + +RTMP in curl is powered by the 3rd party library librtmp. + + - RTMP is barely used by curl users (2.2% in the 2025 survey) + - librtmp has no test cases, makes no proper releases and has not had a single + commit within the last year + - librtmp parses the URL itself and requires non-compliant URLs for this + - we have no RTMP tests + +Support for RTMP in libcurl gets removed in April 2026. + +## CMake 3.17 and earlier + +We remove support for CMake <3.18 in April 2026. + +CMake 3.18 was released on 2020-07-15. ## Past removals @@ -88,3 +74,6 @@ We remove the OpenSSL-QUIC backend in March 2026. - BearSSL (removed in 8.15.0) - msh3 (removed in 8.16.0) - winbuild build system (removed in 8.17.0) + - Windows CE (removed in 8.18.0) + - Support for Visual Studio 2008 (removed in 8.18.0) + - OpenSSL 1.1.1 and older (removed in 8.18.0) diff --git a/docs/DISTROS.md b/docs/DISTROS.md index e852b797d29f..8810cc999150 100644 --- a/docs/DISTROS.md +++ b/docs/DISTROS.md @@ -49,8 +49,8 @@ archives](https://curl.se/mail/list.cgi?list=curl-distros)). *Rolling Release* -- curl package source and patches: https://git.buildroot.net/buildroot/tree/package/libcurl -- curl issues: https://bugs.buildroot.org/buglist.cgi?quicksearch=curl +- curl package source and patches: **missing URL** +- curl issues: **missing URL** ## Chimera @@ -165,7 +165,7 @@ unless it is specific to Homebrew's way of packaging software. - curl: https://svnweb.mageia.org/packages/cauldron/curl/current/SPECS/curl.spec?view=markup - curl issues: https://bugs.mageia.org/buglist.cgi?bug_status=NEW&bug_status=UNCONFIRMED&bug_status=NEEDINFO&bug_status=UPSTREAM&bug_status=ASSIGNED&component=RPM%20Packages&f1=cf_rpmpkg&list_id=176576&o1=casesubstring&product=Mageia&query_format=advanced&v1=curl - curl patches: https://svnweb.mageia.org/packages/cauldron/curl/current/SOURCES/ -- curl patches in stable distro releases: https://svnweb.mageia.org/packages/updates//curl/current/SOURCES/ +- curl patches in stable distro releases: https://svnweb.mageia.org/packages/updates/9/curl/current/SOURCES/ - curl security: https://advisories.mageia.org/src_curl.html ## MSYS2 @@ -188,9 +188,9 @@ unless it is specific to Homebrew's way of packaging software. *Rolling Release* -- curl: https://github.com/lordmulder/cURL-build-win32 -- curl issues: https://github.com/lordmulder/cURL-build-win32/issues -- curl patches: https://github.com/lordmulder/cURL-build-win32/tree/master/patch +- curl: https://github.com/lordmulder/curl-build-win32 +- curl issues: https://github.com/lordmulder/curl-build-win32/issues +- curl patches: https://github.com/lordmulder/curl-build-win32/tree/master/patch ## NixOS @@ -222,6 +222,12 @@ can also be used on other distributions - curl issues: https://support.oracle.com/ (requires support contract) - curl patches: https://github.com/oracle/solaris-userland/tree/master/components/curl/patches +## OpenBSD + +- curl: https://github.com/openbsd/ports/tree/master/net/curl +- curl issues: https://www.openbsd.org/mail.html (ports mailing list) +- curl patches: https://github.com/openbsd/ports/tree/master/net/curl/patches + ## OpenEmbedded / Yocto Project *Rolling Release* @@ -250,7 +256,7 @@ can also be used on other distributions ## Rocky Linux - curl: https://git.rockylinux.org/staging/rpms/curl/-/blob/r9/SPECS/curl.spec -- curl issues: https://bugs.rockylinux.org +- curl issues: https://bugs.rockylinux.org/ - curl patches: https://git.rockylinux.org/staging/rpms/curl/-/tree/r9/SOURCES ## SerenityOS diff --git a/docs/ECH.md b/docs/ECH.md index d39f4b2f36a2..042719245c0c 100644 --- a/docs/ECH.md +++ b/docs/ECH.md @@ -22,9 +22,8 @@ To build the OpenSSL project's ECH feature branch: ```sh cd $HOME/code -git clone https://github.com/openssl/openssl +git clone https://github.com/openssl/openssl --branch feature/ech cd openssl -git checkout feature/ech ./config --libdir=lib --prefix=$HOME/code/openssl-local-inst ...stuff... make -j8 @@ -77,10 +76,8 @@ The above works for these test sites: ```sh https://defo.ie/ech-check.php -https://draft-13.esni.defo.ie:8413/stats -https://draft-13.esni.defo.ie:8414/stats https://crypto.cloudflare.com/cdn-cgi/trace -https://tls-ech.dev +https://tls-ech.dev/ ``` The list above has 4 different server technologies, implemented by 3 different diff --git a/docs/FAQ b/docs/FAQ deleted file mode 100644 index 640dc1ab2a87..000000000000 --- a/docs/FAQ +++ /dev/null @@ -1,1559 +0,0 @@ - _ _ ____ _ - ___| | | | _ \| | - / __| | | | |_) | | - | (__| |_| | _ <| |___ - \___|\___/|_| \_\_____| - -FAQ - - 1. Philosophy - 1.1 What is cURL? - 1.2 What is libcurl? - 1.3 What is curl not? - 1.4 When will you make curl do XXXX ? - 1.5 Who makes curl? - 1.6 What do you get for making curl? - 1.7 What about CURL from curl.com? - 1.8 I have a problem, who do I mail? - 1.9 Where do I buy commercial support for curl? - 1.10 How many are using curl? - 1.11 Why do you not update ca-bundle.crt - 1.12 I have a problem, who can I chat with? - 1.13 curl's ECCN number? - 1.14 How do I submit my patch? - 1.15 How do I port libcurl to my OS? - - 2. Install Related Problems - 2.1 configure fails when using static libraries - 2.2 Does curl work/build with other SSL libraries? - 2.3 How do I upgrade curl.exe in Windows? - 2.4 Does curl support SOCKS (RFC 1928) ? - - 3. Usage Problems - 3.1 curl: (1) SSL is disabled, https: not supported - 3.2 How do I tell curl to resume a transfer? - 3.3 Why does my posting using -F not work? - 3.4 How do I tell curl to run custom FTP commands? - 3.5 How can I disable the Accept: */* header? - 3.6 Does curl support ASP, XML, XHTML or HTML version Y? - 3.7 Can I use curl to delete/rename a file through FTP? - 3.8 How do I tell curl to follow HTTP redirects? - 3.9 How do I use curl in my favorite programming language? - 3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP? - 3.11 How do I POST with a different Content-Type? - 3.12 Why do FTP-specific features over HTTP proxy fail? - 3.13 Why do my single/double quotes fail? - 3.14 Does curl support JavaScript or PAC (automated proxy config)? - 3.15 Can I do recursive fetches with curl? - 3.16 What certificates do I need when I use SSL? - 3.17 How do I list the root directory of an FTP server? - 3.18 Can I use curl to send a POST/PUT and not wait for a response? - 3.19 How do I get HTTP from a host using a specific IP address? - 3.20 How to SFTP from my user's home directory? - 3.21 Protocol xxx not supported or disabled in libcurl - 3.22 curl -X gives me HTTP problems - - 4. Running Problems - 4.2 Why do I get problems when I use & or % in the URL? - 4.3 How can I use {, }, [ or ] to specify multiple URLs? - 4.4 Why do I get downloaded data even though the webpage does not exist? - 4.5 Why do I get return code XXX from an HTTP server? - 4.5.1 "400 Bad Request" - 4.5.2 "401 Unauthorized" - 4.5.3 "403 Forbidden" - 4.5.4 "404 Not Found" - 4.5.5 "405 Method Not Allowed" - 4.5.6 "301 Moved Permanently" - 4.6 Can you tell me what error code 142 means? - 4.7 How do I keep usernames and passwords secret in curl command lines? - 4.8 I found a bug - 4.9 curl cannot authenticate to a server that requires NTLM? - 4.10 My HTTP request using HEAD, PUT or DELETE does not work - 4.11 Why do my HTTP range requests return the full document? - 4.12 Why do I get "certificate verify failed" ? - 4.13 Why is curl -R on Windows one hour off? - 4.14 Redirects work in browser but not with curl - 4.15 FTPS does not work - 4.16 My HTTP POST or PUT requests are slow - 4.17 Non-functional connect timeouts on Windows - 4.18 file:// URLs containing drive letters (Windows, NetWare) - 4.19 Why does not curl return an error when the network cable is unplugged? - 4.20 curl does not return error for HTTP non-200 responses - - 5. libcurl Issues - 5.1 Is libcurl thread-safe? - 5.2 How can I receive all data into a large memory chunk? - 5.3 How do I fetch multiple files with libcurl? - 5.4 Does libcurl do Winsock initialization on Win32 systems? - 5.5 Does CURLOPT_WRITEDATA and CURLOPT_READDATA work on Win32 ? - 5.6 What about Keep-Alive or persistent connections? - 5.7 Link errors when building libcurl on Windows - 5.8 libcurl.so.X: open failed: No such file or directory - 5.9 How does libcurl resolve hostnames? - 5.10 How do I prevent libcurl from writing the response to stdout? - 5.11 How do I make libcurl not receive the whole HTTP response? - 5.12 Can I make libcurl fake or hide my real IP address? - 5.13 How do I stop an ongoing transfer? - 5.14 Using C++ non-static functions for callbacks? - 5.15 How do I get an FTP directory listing? - 5.16 I want a different time-out - 5.17 Can I write a server with libcurl? - 5.18 Does libcurl use threads? - - 6. License Issues - 6.1 I have a GPL program, can I use the libcurl library? - 6.2 I have a closed-source program, can I use the libcurl library? - 6.3 I have a BSD licensed program, can I use the libcurl library? - 6.4 I have a program that uses LGPL libraries, can I use libcurl? - 6.5 Can I modify curl/libcurl for my program and keep the changes secret? - 6.6 Can you please change the curl/libcurl license to XXXX? - 6.7 What are my obligations when using libcurl in my commercial apps? - - 7. PHP/CURL Issues - 7.1 What is PHP/CURL? - 7.2 Who wrote PHP/CURL? - 7.3 Can I perform multiple requests using the same handle? - 7.4 Does PHP/CURL have dependencies? - - 8. Development - 8.1 Why does curl use C89? - 8.2 Will curl be rewritten? - -============================================================================== - -1. Philosophy - - 1.1 What is cURL? - - cURL is the name of the project. The name is a play on 'Client for URLs', - originally with URL spelled in uppercase to make it obvious it deals with - URLs. The fact it can also be read as 'see URL' also helped, it works as - an abbreviation for "Client URL Request Library" or why not the recursive - version: "curl URL Request Library". - - The cURL project produces two products: - - libcurl - - A client-side URL transfer library, supporting 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. - - libcurl supports HTTPS certificates, HTTP POST, HTTP PUT, FTP uploading, - Kerberos, SPNEGO, HTTP form based upload, proxies, cookies, user+password - authentication, file transfer resume, http proxy tunneling and more. - - libcurl is highly portable, it builds and works identically on numerous - platforms, including Solaris, NetBSD, FreeBSD, OpenBSD, Darwin, HP-UX, - IRIX, AIX, Tru64, Linux, UnixWare, HURD, Windows, Amiga, OS/2, macOS, - Ultrix, QNX, OpenVMS, RISC OS, Novell NetWare, DOS, Symbian, OSF, Android, - Minix, IBM TPF and more... - - libcurl is free, thread-safe, IPv6 compatible, feature rich, well - supported and fast. - - curl - - A command line tool for getting or sending data using URL syntax. - - Since curl uses libcurl, curl supports the same wide range of common - Internet protocols that libcurl does. - - We pronounce curl with an initial k sound. It rhymes with words like girl - and earl. This is a short WAV file to help you: - - https://media.merriam-webster.com/soundc11/c/curl0001.wav - - There are numerous sub-projects and related projects that also use the word - curl in the project names in various combinations, but you should take - notice that this FAQ is directed at the command-line tool named curl (and - libcurl the library), and may therefore not be valid for other curl-related - projects. (There is however a small section for the PHP/CURL in this FAQ.) - - 1.2 What is libcurl? - - libcurl is a reliable and portable library for doing Internet data transfers - using one or more of its supported Internet protocols. - - You can use libcurl freely in your application, be it open source, - commercial or closed-source. - - libcurl is most probably the most portable, most powerful and most often - used C-based multi-platform file transfer library on this planet - be it - open source or commercial. - - 1.3 What is curl not? - - curl is not a wget clone. That is a common misconception. Never, during - curl's development, have we intended curl to replace wget or compete on its - market. curl is targeted at single-shot file transfers. - - curl is not a website mirroring program. If you want to use curl to mirror - something: fine, go ahead and write a script that wraps around curl or use - libcurl to make it reality. - - curl is not an FTP site mirroring program. Sure, get and send FTP with curl - but if you want systematic and sequential behavior you should write a - script (or write a new program that interfaces libcurl) and do it. - - curl is not a PHP tool, even though it works perfectly well when used from - or with PHP (when using the PHP/CURL module). - - curl is not a program for a single operating system. curl exists, compiles, - builds and runs under a wide range of operating systems, including all - modern Unixes (and a bunch of older ones too), Windows, Amiga, OS/2, macOS, - QNX etc. - - 1.4 When will you make curl do XXXX ? - - We love suggestions of what to change in order to make curl and libcurl - better. We do however believe in a few rules when it comes to the future of - curl: - - curl -- the command line tool -- is to remain a non-graphical command line - tool. If you want GUIs or fancy scripting capabilities, you should look for - another tool that uses libcurl. - - We do not add things to curl that other small and available tools already do - well at the side. curl's output can be piped into another program or - redirected to another file for the next program to interpret. - - We focus on protocol related issues and improvements. If you want to do more - magic with the supported protocols than curl currently does, chances are - good we will agree. If you want to add more protocols, we may agree. - - If you want someone else to do all the work while you wait for us to - implement it for you, that is not a friendly attitude. We spend a - considerable time already on maintaining and developing curl. In order to - get more out of us, you should consider trading in some of your time and - effort in return. Simply go to the GitHub repository which resides at - https://github.com/curl/curl, fork the project, and create pull requests - with your proposed changes. - - If you write the code, chances are better that it will get into curl faster. - - 1.5 Who makes curl? - - curl and libcurl are not made by any single individual. Daniel Stenberg is - project leader and main developer, but other persons' submissions are - important and crucial. Anyone can contribute and post their changes and - improvements and have them inserted in the main sources (of course on the - condition that developers agree that the fixes are good). - - The full list of all contributors is found in the docs/THANKS file. - - curl is developed by a community, with Daniel at the wheel. - - 1.6 What do you get for making curl? - - Project cURL is entirely free and open. We do this voluntarily, mostly in - our spare time. Companies may pay individual developers to work on curl. - This is not controlled by nor supervised in any way by the curl project. - - We get help from companies. Haxx provides website, bandwidth, mailing lists - etc, GitHub hosts the primary git repository and other services like the bug - tracker at https://github.com/curl/curl. Also again, some companies have - sponsored certain parts of the development in the past and I hope some will - continue to do so in the future. - - If you want to support our project, consider a donation or a banner-program - or even better: by helping us with coding, documenting or testing etc. - - See also: https://curl.se/sponsors.html - - 1.7 What about CURL from curl.com? - - During the summer of 2001, curl.com was busy advertising their client-side - programming language for the web, named CURL. - - We are in no way associated with curl.com or their CURL programming - language. - - Our project name curl has been in effective use since 1998. We were not the - first computer related project to use the name "curl" and do not claim any - rights to the name. - - We recognize that we will be living in parallel with curl.com and wish them - every success. - - 1.8 I have a problem, who do I mail? - - Please do not mail any single individual unless you really need to. Keep - curl-related questions on a suitable mailing list. All available mailing - lists are listed in the MANUAL document and online at - https://curl.se/mail/ - - Keeping curl-related questions and discussions on mailing lists allows - others to join in and help, to share their ideas, to contribute their - suggestions and to spread their wisdom. Keeping discussions on public mailing - lists also allows for others to learn from this (both current and future - users thanks to the web based archives of the mailing lists), thus saving us - from having to repeat ourselves even more. Thanks for respecting this. - - If you have found or simply suspect a security problem in curl or libcurl, - submit all the details at https://hackerone.one/curl. On there we keep the - issue private while we investigate, confirm it, work and validate a fix and - agree on a time schedule for publication etc. That way we produce a fix in a - timely manner before the flaw is announced to the world, reducing the impact - the problem risks having on existing users. - - Security issues can also be taking to the curl security team by emailing - security at curl.se (closed list of receivers, mails are not disclosed). - - 1.9 Where do I buy commercial support for curl? - - curl is fully open source. It means you can hire any skilled engineer to fix - your curl-related problems. - - We list available alternatives on the curl website: - https://curl.se/support.html - - 1.10 How many are using curl? - - It is impossible to tell. - - We do not know how many users that knowingly have installed and use curl. - - We do not know how many users that use curl without knowing that they are in - fact using it. - - We do not know how many users that downloaded or installed curl and then - never use it. - - In 2020, we estimate that curl runs in roughly ten billion installations - world wide. - - 1.11 Why do you not update ca-bundle.crt - - In the cURL project we have decided not to attempt to keep this file updated - (or even present) since deciding what to add to a ca cert bundle is an - undertaking we have not been ready to accept, and the one we can get from - Mozilla is perfectly fine so there is no need to duplicate that work. - - Today, with many services performed over HTTPS, every operating system - should come with a default ca cert bundle that can be deemed somewhat - trustworthy and that collection (if reasonably updated) should be deemed to - be a lot better than a private curl version. - - If you want the most recent collection of ca certs that Mozilla Firefox - uses, we recommend that you extract the collection yourself from Mozilla - Firefox (by running 'make ca-bundle), or by using our online service setup - for this purpose: https://curl.se/docs/caextract.html - - 1.12 I have a problem who, can I chat with? - - There is a bunch of friendly people hanging out in the #curl channel on the - IRC network libera.chat. If you are polite and nice, chances are good that - you can get -- or provide -- help instantly. - - 1.13 curl's ECCN number? - - The US government restricts exports of software that contains or uses - cryptography. When doing so, the Export Control Classification Number (ECCN) - is used to identify the level of export control etc. - - Apache Software Foundation gives a good explanation of ECCNs at - https://www.apache.org/dev/crypto.html - - We believe curl's number might be ECCN 5D002, another possibility is - 5D992. It seems necessary to write them (the authority that administers ECCN - numbers), asking to confirm. - - Comprehensible explanations of the meaning of such numbers and how to obtain - them (resp.) are here - - https://www.bis.doc.gov/licensing/exportingbasics.htm - https://www.bis.doc.gov/licensing/do_i_needaneccn.html - - An incomprehensible description of the two numbers above is here - https://www.bis.doc.gov/index.php/documents/new-encryption/1653-ccl5-pt2-3 - - 1.14 How do I submit my patch? - - We strongly encourage you to submit changes and improvements directly as - "pull requests" on GitHub: https://github.com/curl/curl/pulls - - If you for any reason cannot or will not deal with GitHub, send your patch to - the curl-library mailing list. We are many subscribers there and there are - lots of people who can review patches, comment on them and "receive" them - properly. - - Lots of more details are found in the CONTRIBUTE.md and INTERNALS.md - documents. - - 1.15 How do I port libcurl to my OS? - - Here's a rough step-by-step: - - 1. copy a suitable lib/config-*.h file as a start to lib/config-[youros].h - - 2. edit lib/config-[youros].h to match your OS and setup - - 3. edit lib/curl_setup.h to include config-[youros].h when your OS is - detected by the preprocessor, in the style others already exist - - 4. compile lib/*.c and make them into a library - - -2. Install Related Problems - - 2.1 configure fails when using static libraries - - You may find that configure fails to properly detect the entire dependency - chain of libraries when you provide static versions of the libraries that - configure checks for. - - The reason why static libraries is much harder to deal with is that for them - we do not get any help but the script itself must know or check what more - libraries that are needed (with shared libraries, that dependency "chain" is - handled automatically). This is an error-prone process and one that also - tends to vary over time depending on the release versions of the involved - components and may also differ between operating systems. - - For that reason, configure does few attempts to actually figure this out and - you are instead encouraged to set LIBS and LDFLAGS accordingly when you - invoke configure, and point out the needed libraries and set the necessary - flags yourself. - - 2.2 Does curl work with other SSL libraries? - - curl has been written to use a generic SSL function layer internally, and - that SSL functionality can then be provided by one out of many different SSL - backends. - - curl can be built to use one of the following SSL alternatives: OpenSSL, - LibreSSL, BoringSSL, AWS-LC, GnuTLS, wolfSSL, mbedTLS, Schannel (native - Windows) or Rustls. They all have their pros and cons, and we try to - maintain a comparison of them here: https://curl.se/docs/ssl-compared.html - - 2.3 How do I upgrade curl.exe in Windows? - - The curl tool that is shipped as an integrated component of Windows 10 and - Windows 11 is managed by Microsoft. If you were to delete the file or - replace it with a newer version downloaded from https://curl.se/windows, - then Windows Update will cease to work on your system. - - There is no way to independently force an upgrade of the curl.exe that is - part of Windows other than through the regular Windows update process. There - is also nothing the curl project itself can do about this, since this is - managed and controlled entirely by Microsoft as owners of the operating - system. - - You can always download and install the latest version of curl for Windows - from https://curl.se/windows into a separate location. - - 2.4 Does curl support SOCKS (RFC 1928) ? - - Yes, SOCKS 4 and 5 are supported. - -3. Usage problems - - 3.1 curl: (1) SSL is disabled, https: not supported - - If you get this output when trying to get anything from an HTTPS server, it - means that the instance of curl/libcurl that you are using was built without - support for this protocol. - - This could have happened if the configure script that was run at build time - could not find all libs and include files curl requires for SSL to work. If - the configure script fails to find them, curl is simply built without SSL - support. - - To get HTTPS support into a curl that was previously built but that reports - that HTTPS is not supported, you should dig through the document and logs - and check out why the configure script does not find the SSL libs and/or - include files. - - Also, check out the other paragraph in this FAQ labeled "configure does not - find OpenSSL even when it is installed". - - 3.2 How do I tell curl to resume a transfer? - - curl supports resumed transfers both ways on both FTP and HTTP. - Try the -C option. - - 3.3 Why does my posting using -F not work? - - You cannot arbitrarily use -F or -d, the choice between -F or -d depends on - the HTTP operation you need curl to do and what the web server that will - receive your post expects. - - If the form you are trying to submit uses the type 'multipart/form-data', - then and only then you must use the -F type. In all the most common cases, - you should use -d which then causes a posting with the type - 'application/x-www-form-urlencoded'. - - This is described in some detail in the MANUAL and TheArtOfHttpScripting - documents, and if you do not understand it the first time, read it again - before you post questions about this to the mailing list. Also, try reading - through the mailing list archives for old postings and questions regarding - this. - - 3.4 How do I tell curl to run custom FTP commands? - - You can tell curl to perform optional commands both before and/or after a - file transfer. Study the -Q/--quote option. - - Since curl is used for file transfers, you do not normally use curl to - perform FTP commands without transferring anything. Therefore you must - always specify a URL to transfer to/from even when doing custom FTP - commands, or use -I which implies the "no body" option sent to libcurl. - - 3.5 How can I disable the Accept: */* header? - - You can change all internally generated headers by adding a replacement with - the -H/--header option. By adding a header with empty contents you safely - disable that one. Use -H "Accept:" to disable that specific header. - - 3.6 Does curl support ASP, XML, XHTML or HTML version Y? - - To curl, all contents are alike. It does not matter how the page was - generated. It may be ASP, PHP, Perl, shell-script, SSI or plain HTML - files. There is no difference to curl and it does not even know what kind of - language that generated the page. - - See also item 3.14 regarding JavaScript. - - 3.7 Can I use curl to delete/rename a file through FTP? - - Yes. You specify custom FTP commands with -Q/--quote. - - One example would be to delete a file after you have downloaded it: - - curl -O ftp://example.com/coolfile -Q '-DELE coolfile' - - or rename a file after upload: - - curl -T infile ftp://example.com/dir/ -Q "-RNFR infile" -Q "-RNTO newname" - - 3.8 How do I tell curl to follow HTTP redirects? - - curl does not follow so-called redirects by default. The Location: header - that informs the client about this is only interpreted if you are using the - -L/--location option. As in: - - curl -L http://example.com - - Not all redirects are HTTP ones, see 4.14 - - 3.9 How do I use curl in my favorite programming language? - - Many programming languages have interfaces/bindings that allow you to use - curl without having to use the command line tool. If you are fluent in such - a language, you may prefer to use one of these interfaces instead. - - Find out more about which languages that support curl directly, and how to - install and use them, in the libcurl section of the curl website: - https://curl.se/libcurl/ - - All the various bindings to libcurl are made by other projects and people, - outside of the cURL project. The cURL project itself only produces libcurl - with its plain C API. If you do not find anywhere else to ask you can ask - about bindings on the curl-library list too, but be prepared that people on - that list may not know anything about bindings. - - In December 2021, there were interfaces available for the following - languages: Ada95, Basic, C, C++, Ch, Cocoa, D, Delphi, Dylan, Eiffel, - Euphoria, Falcon, Ferite, Gambas, glib/GTK+, Go, Guile, Harbour, Haskell, - Java, Julia, Lisp, Lua, Mono, .NET, node.js, Object-Pascal, OCaml, Pascal, - Perl, PHP, PostgreSQL, Python, R, Rexx, Ring, RPG, Ruby, Rust, Scheme, - Scilab, S-Lang, Smalltalk, SP-Forth, SPL, Tcl, Visual Basic, Visual FoxPro, - Q, wxwidgets, XBLite and Xoho. By the time you read this, additional ones - may have appeared. - - 3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP? - - curl adheres to the HTTP spec, which basically means you can play with *any* - protocol that is built on top of HTTP. Protocols such as SOAP, WebDAV and - XML-RPC are all such ones. You can use -X to set custom requests and -H to - set custom headers (or replace internally generated ones). - - Using libcurl is of course just as good and you would just use the proper - library options to do the same. - - 3.11 How do I POST with a different Content-Type? - - You can always replace the internally generated headers with -H/--header. - To make a simple HTTP POST with text/xml as content-type, do something like: - - curl -d "datatopost" -H "Content-Type: text/xml" [URL] - - 3.12 Why do FTP-specific features over HTTP proxy fail? - - Because when you use an HTTP proxy, the protocol spoken on the network will - be HTTP, even if you specify an FTP URL. This effectively means that you - normally cannot use FTP-specific features such as FTP upload and FTP quote - etc. - - There is one exception to this rule, and that is if you can "tunnel through" - the given HTTP proxy. Proxy tunneling is enabled with a special option (-p) - and is generally not available as proxy admins usually disable tunneling to - ports other than 443 (which is used for HTTPS access through proxies). - - 3.13 Why do my single/double quotes fail? - - To specify a command line option that includes spaces, you might need to - put the entire option within quotes. Like in: - - curl -d " with spaces " example.com - - or perhaps - - curl -d ' with spaces ' example.com - - Exactly what kind of quotes and how to do this is entirely up to the shell - or command line interpreter that you are using. For most Unix shells, you - can more or less pick either single (') or double (") quotes. For - Windows/DOS command prompts you must use double (") quotes, and if the - option string contains inner double quotes you can escape them with a - backslash. - - For Windows powershell the arguments are not always passed on as expected - because curl is not a powershell script. You may or may not be able to use - single quotes. To escape inner double quotes seems to require a - backslash-backtick escape sequence and the outer quotes as double quotes. - - Please study the documentation for your particular environment. Examples in - the curl docs will use a mix of both of these as shown above. You must - adjust them to work in your environment. - - Remember that curl works and runs on more operating systems than most single - individuals have ever tried. - - 3.14 Does curl support JavaScript or PAC (automated proxy config)? - - Many webpages do magic stuff using embedded JavaScript. curl and libcurl - have no built-in support for that, so it will be treated just like any other - contents. - - .pac files are a Netscape invention and are sometimes used by organizations - to allow them to differentiate which proxies to use. The .pac contents is - just a JavaScript program that gets invoked by the browser and that returns - the name of the proxy to connect to. Since curl does not support JavaScript, - it cannot support .pac proxy configuration either. - - Some workarounds usually suggested to overcome this JavaScript dependency: - - 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. - - 3.15 Can I do recursive fetches with curl? - - No. curl itself has no code that performs recursive operations, such as - those performed by wget and similar tools. - - There exists wrapper scripts with that functionality (for example the - curlmirror perl script), and you can write programs based on libcurl to do - it, but the command line tool curl itself cannot. - - 3.16 What certificates do I need when I use SSL? - - There are three different kinds of "certificates" to keep track of when we - talk about using SSL-based protocols (HTTPS or FTPS) using curl or libcurl. - - CLIENT CERTIFICATE - - The server you communicate with may require that you can provide this in - order to prove that you actually are who you claim to be. If the server - does not require this, you do not need a client certificate. - - A client certificate is always used together with a private key, and the - private key has a pass phrase that protects it. - - SERVER CERTIFICATE - - The server you communicate with has a server certificate. You can and should - verify this certificate to make sure that you are truly talking to the real - server and not a server impersonating it. - - CERTIFICATE AUTHORITY CERTIFICATE ("CA cert") - - You often have several CA certs in a CA cert bundle that can be used to - verify a server certificate that was signed by one of the authorities in the - bundle. curl does not come with a CA cert bundle but most curl installs - provide one. You can also override the default. - - The server certificate verification process is made by using a Certificate - Authority certificate ("CA cert") that was used to sign the server - certificate. Server certificate verification is enabled by default in curl - and libcurl and is often the reason for problems as explained in FAQ entry - 4.12 and the SSLCERTS document - (https://curl.se/docs/sslcerts.html). Server certificates that are - "self-signed" or otherwise signed by a CA that you do not have a CA cert - for, cannot be verified. If the verification during a connect fails, you are - refused access. You then need to explicitly disable the verification to - connect to the server. - - 3.17 How do I list the root directory of an FTP server? - - There are two ways. The way defined in the RFC is to use an encoded slash - in the first path part. List the "/tmp" directory like this: - - curl ftp://ftp.example.com/%2ftmp/ - - or the not-quite-kosher-but-more-readable way, by simply starting the path - section of the URL with a slash: - - curl ftp://ftp.example.com//tmp/ - - 3.18 Can I use curl to send a POST/PUT and not wait for a response? - - No. - - You can easily write your own program using libcurl to do such stunts. - - 3.19 How do I get HTTP from a host using a specific IP address? - - For example, you may be trying out a website installation that is not yet in - the DNS. Or you have a site using multiple IP addresses for a given host - name and you want to address a specific one out of the set. - - Set a custom Host: header that identifies the server name you want to reach - but use the target IP address in the URL: - - curl --header "Host: www.example.com" http://127.0.0.1/ - - You can also opt to add faked hostname entries to curl with the --resolve - option. That has the added benefit that things like redirects will also work - properly. The above operation would instead be done as: - - curl --resolve www.example.com:80:127.0.0.1 http://www.example.com/ - - 3.20 How to SFTP from my user's home directory? - - Contrary to how FTP works, SFTP and SCP URLs specify the exact directory to - work with. It means that if you do not specify that you want the user's home - directory, you get the actual root directory. - - To specify a file in your user's home directory, you need to use the correct - URL syntax which for SFTP might look similar to: - - curl -O -u user:password sftp://example.com/~/file.txt - - and for SCP it is just a different protocol prefix: - - curl -O -u user:password scp://example.com/~/file.txt - - 3.21 Protocol xxx not supported or disabled in libcurl - - When passing on a URL to curl to use, it may respond that the particular - protocol is not supported or disabled. The particular way this error message - is phrased is because curl does not make a distinction internally of whether - a particular protocol is not supported (i.e. never got any code added that - knows how to speak that protocol) or if it was explicitly disabled. curl can - be built to only support a given set of protocols, and the rest would then - be disabled or not supported. - - Note that this error will also occur if you pass a wrongly spelled protocol - part as in "htpt://example.com" or as in the less evident case if you prefix - the protocol part with a space as in " http://example.com/". - - 3.22 curl -X gives me HTTP problems - - In normal circumstances, -X should hardly ever be used. - - By default you use curl without explicitly saying which request method to - use when the URL identifies an HTTP transfer. If you just pass in a URL like - "curl http://example.com" it will use GET. If you use -d or -F curl will use - POST, -I will cause a HEAD and -T will make it a PUT. - - If for whatever reason you are not happy with these default choices that curl - does for you, you can override those request methods by specifying -X - [WHATEVER]. This way you can for example send a DELETE by doing "curl -X - DELETE [URL]". - - It is thus pointless to do "curl -XGET [URL]" as GET would be used anyway. - In the same vein it is pointless to do "curl -X POST -d data [URL]". You can - make a fun and somewhat rare request that sends a request-body in a GET - request with something like "curl -X GET -d data [URL]" - - Note that -X does not actually change curl's behavior as it only modifies the - actual string sent in the request, but that may of course trigger a - different set of events. - - Accordingly, by using -XPOST on a command line that for example would follow - a 303 redirect, you will effectively prevent curl from behaving - correctly. Be aware. - - -4. Running Problems - - 4.2 Why do I get problems when I use & or % in the URL? - - In general Unix shells, the & symbol is treated specially and when used, it - runs the specified command in the background. To safely send the & as a part - of a URL, you should quote the entire URL by using single (') or double (") - quotes around it. Similar problems can also occur on some shells with other - characters, including ?*!$~(){}<>\|;`. When in doubt, quote the URL. - - An example that would invoke a remote CGI that uses &-symbols could be: - - curl 'http://www.example.com/cgi-bin/query?text=yes&q=curl' - - In Windows, the standard DOS shell treats the percent sign specially and you - need to use TWO percent signs for each single one you want to use in the - URL. - - If you want a literal percent sign to be part of the data you pass in a POST - using -d/--data you must encode it as '%25' (which then also needs the - percent sign doubled on Windows machines). - - 4.3 How can I use {, }, [ or ] to specify multiple URLs? - - Because those letters have a special meaning to the shell, to be used in - a URL specified to curl you must quote them. - - An example that downloads two URLs (sequentially) would be: - - curl '{curl,www}.haxx.se' - - To be able to use those characters as actual parts of the URL (without using - them for the curl URL "globbing" system), use the -g/--globoff option: - - curl -g 'www.example.com/weirdname[].html' - - 4.4 Why do I get downloaded data even though the webpage does not exist? - - curl asks remote servers for the page you specify. If the page does not exist - at the server, the HTTP protocol defines how the server should respond and - that means that headers and a "page" will be returned. That is simply how - HTTP works. - - By using the --fail option you can tell curl explicitly to not get any data - if the HTTP return code does not say success. - - 4.5 Why do I get return code XXX from an HTTP server? - - RFC 2616 clearly explains the return codes. This is a short transcript. Go - read the RFC for exact details: - - 4.5.1 "400 Bad Request" - - The request could not be understood by the server due to malformed - syntax. The client SHOULD NOT repeat the request without modifications. - - 4.5.2 "401 Unauthorized" - - The request requires user authentication. - - 4.5.3 "403 Forbidden" - - The server understood the request, but is refusing to fulfill it. - Authorization will not help and the request SHOULD NOT be repeated. - - 4.5.4 "404 Not Found" - - The server has not found anything matching the Request-URI. No indication - is given as to whether the condition is temporary or permanent. - - 4.5.5 "405 Method Not Allowed" - - The method specified in the Request-Line is not allowed for the resource - identified by the Request-URI. The response MUST include an Allow header - containing a list of valid methods for the requested resource. - - 4.5.6 "301 Moved Permanently" - - If you get this return code and an HTML output similar to this: - -

Moved Permanently

The document has moved here. - - it might be because you requested a directory URL but without the trailing - slash. Try the same operation again _with_ the trailing URL, or use the - -L/--location option to follow the redirection. - - 4.6 Can you tell me what error code 142 means? - - All curl error codes are described at the end of the man page, in the - section called "EXIT CODES". - - Error codes that are larger than the highest documented error code means - that curl has exited due to a crash. This is a serious error, and we - appreciate a detailed bug report from you that describes how we could go - ahead and repeat this. - - 4.7 How do I keep usernames and passwords secret in curl command lines? - - This problem has two sides: - - The first part is to avoid having clear-text passwords in the command line - so that they do not appear in 'ps' outputs and similar. That is easily - avoided by using the "-K" option to tell curl to read parameters from a file - or stdin to which you can pass the secret info. curl itself will also - attempt to "hide" the given password by blanking out the option - this - does not work on all platforms. - - To keep the passwords in your account secret from the rest of the world is - not a task that curl addresses. You could of course encrypt them somehow to - at least hide them from being read by human eyes, but that is not what - anyone would call security. - - Also note that regular HTTP (using Basic authentication) and FTP passwords - are sent as cleartext across the network. All it takes for anyone to fetch - them is to listen on the network. Eavesdropping is easy. Use more secure - authentication methods (like Digest, Negotiate or even NTLM) or consider the - SSL-based alternatives HTTPS and FTPS. - - 4.8 I found a bug - - It is not a bug if the behavior is documented. Read the docs first. - Especially check out the KNOWN_BUGS file, it may be a documented bug. - - If it is a problem with a binary you have downloaded or a package for your - particular platform, try contacting the person who built the package/archive - you have. - - If there is a bug, read the BUGS document first. Then report it as described - in there. - - 4.9 curl cannot authenticate to a server that requires NTLM? - - NTLM support requires OpenSSL, GnuTLS, mbedTLS or Microsoft Windows - libraries at build-time to provide this functionality. - - 4.10 My HTTP request using HEAD, PUT or DELETE does not work - - Many web servers allow or demand that the administrator configures the - server properly for these requests to work on the web server. - - Some servers seem to support HEAD only on certain kinds of URLs. - - To fully grasp this, try the documentation for the particular server - software you are trying to interact with. This is not anything curl can do - anything about. - - 4.11 Why do my HTTP range requests return the full document? - - Because the range may not be supported by the server, or the server may - choose to ignore it and return the full document anyway. - - 4.12 Why do I get "certificate verify failed" ? - - When you invoke curl and get an error 60 error back it means that curl - could not verify that the server's certificate was good. curl verifies the - certificate using the CA cert bundle and verifying for which names the - certificate has been granted. - - To completely disable the certificate verification, use -k. This does - however enable man-in-the-middle attacks and makes the transfer INSECURE. - We strongly advise against doing this for more than experiments. - - If you get this failure with a CA cert bundle installed and used, the - server's certificate might not be signed by one of the CA's in your CA - store. It might for example be self-signed. You then correct this problem by - obtaining a valid CA cert for the server. Or again, decrease the security by - disabling this check. - - At times, you find that the verification works in your favorite browser but - fails in curl. When this happens, the reason is usually that the server - sends an incomplete cert chain. The server is mandated to send all - "intermediate certificates" but does not. This typically works with browsers - anyway since they A) cache such certs and B) supports AIA which downloads - such missing certificates on demand. This is a server misconfiguration. A - good way to figure out if this is the case it to use the SSL Labs server - test and check the certificate chain: https://www.ssllabs.com/ssltest/ - - Details are also in the SSLCERTS.md document, found online here: - https://curl.se/docs/sslcerts.html - - 4.13 Why is curl -R on Windows one hour off? - - Since curl 7.53.0 this issue should be fixed as long as curl was built with - any modern compiler that allows for a 64-bit curl_off_t type. For older - compilers or prior curl versions it may set a time that appears one hour off. - This happens due to a flaw in how Windows stores and uses file modification - times and it is not easily worked around. For more details read this: - https://www.codeproject.com/Articles/1144/Beating-the-Daylight-Savings-Time-bug-and-getting - - 4.14 Redirects work in browser but not with curl - - curl supports HTTP redirects well (see item 3.8). Browsers generally support - at least two other ways to perform redirects that curl does not: - - Meta tags. You can write an HTML tag that will cause the browser to redirect - to another given URL after a certain time. - - JavaScript. You can write a JavaScript program embedded in an HTML page that - redirects the browser to another given URL. - - There is no way to make curl follow these redirects. You must either - manually figure out what the page is set to do, or write a script that parses - the results and fetches the new URL. - - 4.15 FTPS does not work - - curl supports FTPS (sometimes known as FTP-SSL) both implicit and explicit - mode. - - When a URL is used that starts with FTPS://, curl assumes implicit SSL on - the control connection and will therefore immediately connect and try to - speak SSL. FTPS:// connections default to port 990. - - To use explicit FTPS, you use an FTP:// URL and the --ssl-reqd option (or one - of its related flavors). This is the most common method, and the one - mandated by RFC 4217. This kind of connection will then of course use the - standard FTP port 21 by default. - - 4.16 My HTTP POST or PUT requests are slow - - libcurl makes all POST and PUT requests (except for requests with a small - request body) use the "Expect: 100-continue" header. This header allows the - server to deny the operation early so that libcurl can bail out before having - to send any data. This is useful in authentication cases and others. - - However, many servers do not implement the Expect: stuff properly and if the - server does not respond (positively) within 1 second libcurl will continue - and send off the data anyway. - - You can disable libcurl's use of the Expect: header the same way you disable - any header, using -H / CURLOPT_HTTPHEADER, or by forcing it to use HTTP 1.0. - - 4.17 Non-functional connect timeouts - - In most Windows setups having a timeout longer than 21 seconds make no - difference, as it will only send 3 TCP SYN packets and no more. The second - packet sent three seconds after the first and the third six seconds after - the second. No more than three packets are sent, no matter how long the - timeout is set. - - See option TcpMaxConnectRetransmissions on this page: - https://web.archive.org/web/20160819015101/support.microsoft.com/en-us/kb/175523 - - Also, even on non-Windows systems there may run a firewall or anti-virus - software or similar that accepts the connection but does not actually do - anything else. This will make (lib)curl to consider the connection connected - and thus the connect timeout will not trigger. - - 4.18 file:// URLs containing drive letters (Windows, NetWare) - - When using curl to try to download a local file, one might use a URL - in this format: - - file://D:/blah.txt - - you will find that even if D:\blah.txt does exist, curl returns a 'file - not found' error. - - According to RFC 1738 (https://www.ietf.org/rfc/rfc1738.txt), - file:// URLs must contain a host component, but it is ignored by - most implementations. In the above example, 'D:' is treated as the - host component, and is taken away. Thus, curl tries to open '/blah.txt'. - If your system is installed to drive C:, that will resolve to 'C:\blah.txt', - and if that does not exist you will get the not found error. - - To fix this problem, use file:// URLs with *three* leading slashes: - - file:///D:/blah.txt - - Alternatively, if it makes more sense, specify 'localhost' as the host - component: - - file://localhost/D:/blah.txt - - In either case, curl should now be looking for the correct file. - - 4.19 Why does not curl return an error when the network cable is unplugged? - - Unplugging a cable is not an error situation. The TCP/IP protocol stack - was designed to be fault tolerant, so even though there may be a physical - break somewhere the connection should not be affected, just possibly - delayed. Eventually, the physical break will be fixed or the data will be - re-routed around the physical problem through another path. - - In such cases, the TCP/IP stack is responsible for detecting when the - network connection is irrevocably lost. Since with some protocols it is - perfectly legal for the client to wait indefinitely for data, the stack may - never report a problem, and even when it does, it can take up to 20 minutes - for it to detect an issue. The curl option --keepalive-time enables - keep-alive support in the TCP/IP stack which makes it periodically probe the - connection to make sure it is still available to send data. That should - reliably detect any TCP/IP network failure. - - TCP keep alive will not detect the network going down before the TCP/IP - connection is established (e.g. during a DNS lookup) or using protocols that - do not use TCP. To handle those situations, curl offers a number of timeouts - on its own. --speed-limit/--speed-time will abort if the data transfer rate - falls too low, and --connect-timeout and --max-time can be used to put an - overall timeout on the connection phase or the entire transfer. - - A libcurl-using application running in a known physical environment (e.g. - an embedded device with only a single network connection) may want to act - immediately if its lone network connection goes down. That can be achieved - by having the application monitor the network connection on its own using an - OS-specific mechanism, then signaling libcurl to abort (see also item 5.13). - - 4.20 curl does not return error for HTTP non-200 responses - - Correct. Unless you use -f (--fail). - - When doing HTTP transfers, curl will perform exactly what you are asking it - to do and if successful it will not return an error. You can use curl to - test your web server's "file not found" page (that gets 404 back), you can - use it to check your authentication protected webpages (that gets a 401 - back) and so on. - - The specific HTTP response code does not constitute a problem or error for - curl. It simply sends and delivers HTTP as you asked and if that worked, - everything is fine and dandy. The response code is generally providing more - higher level error information that curl does not care about. The error was - not in the HTTP transfer. - - If you want your command line to treat error codes in the 400 and up range - as errors and thus return a non-zero value and possibly show an error - message, curl has a dedicated option for that: -f (CURLOPT_FAILONERROR in - libcurl speak). - - You can also use the -w option and the variable %{response_code} to extract - the exact response code that was returned in the response. - -5. libcurl Issues - - 5.1 Is libcurl thread-safe? - - Yes. - - We have written the libcurl code specifically adjusted for multi-threaded - programs. libcurl will use thread-safe functions instead of non-safe ones if - your system has such. Note that you must never share the same handle in - multiple threads. - - There may be some exceptions to thread safety depending on how libcurl was - built. Please review the guidelines for thread safety to learn more: - https://curl.se/libcurl/c/threadsafe.html - - 5.2 How can I receive all data into a large memory chunk? - - [ See also the examples/getinmemory.c source ] - - You are in full control of the callback function that gets called every time - there is data received from the remote server. You can make that callback do - whatever you want. You do not have to write the received data to a file. - - One solution to this problem could be to have a pointer to a struct that you - pass to the callback function. You set the pointer using the - CURLOPT_WRITEDATA option. Then that pointer will be passed to the callback - instead of a FILE * to a file: - - /* imaginary struct */ - struct MemoryStruct { - char *memory; - size_t size; - }; - - /* imaginary callback function */ - size_t - WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data) - { - size_t realsize = size * nmemb; - struct MemoryStruct *mem = (struct MemoryStruct *)data; - - mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1); - if (mem->memory) { - memcpy(&(mem->memory[mem->size]), ptr, realsize); - mem->size += realsize; - mem->memory[mem->size] = 0; - } - return realsize; - } - - 5.3 How do I fetch multiple files with libcurl? - - libcurl has excellent support for transferring multiple files. You should - just repeatedly set new URLs with curl_easy_setopt() and then transfer it - with curl_easy_perform(). The handle you get from curl_easy_init() is not - only reusable, but you are even encouraged to reuse it if you can, as that - will enable libcurl to use persistent connections. - - 5.4 Does libcurl do Winsock initialization on Win32 systems? - - Yes, if told to in the curl_global_init() call. - - 5.5 Does CURLOPT_WRITEDATA and CURLOPT_READDATA work on Win32 ? - - Yes, but you cannot open a FILE * and pass the pointer to a DLL and have - that DLL use the FILE * (as the DLL and the client application cannot access - each others' variable memory areas). If you set CURLOPT_WRITEDATA you must - also use CURLOPT_WRITEFUNCTION as well to set a function that writes the - file, even if that simply writes the data to the specified FILE *. - Similarly, if you use CURLOPT_READDATA you must also specify - CURLOPT_READFUNCTION. - - 5.6 What about Keep-Alive or persistent connections? - - curl and libcurl have excellent support for persistent connections when - transferring several files from the same server. curl will attempt to reuse - connections for all URLs specified on the same command line/config file, and - libcurl will reuse connections for all transfers that are made using the - same libcurl handle. - - When you use the easy interface the connection cache is kept within the easy - handle. If you instead use the multi interface, the connection cache will be - kept within the multi handle and will be shared among all the easy handles - that are used within the same multi handle. - - 5.7 Link errors when building libcurl on Windows - - You need to make sure that your project, and all the libraries (both static - and dynamic) that it links against, are compiled/linked against the same run - time library. - - This is determined by the /MD, /ML, /MT (and their corresponding /M?d) - options to the command line compiler. /MD (linking against MSVCRT dll) seems - to be the most commonly used option. - - When building an application that uses the static libcurl library, you must - add -DCURL_STATICLIB to your CFLAGS. Otherwise the linker will look for - dynamic import symbols. If you are using Visual Studio, you need to instead - add CURL_STATICLIB in the "Preprocessor Definitions" section. - - If you get a linker error like "unknown symbol __imp__curl_easy_init ..." you - have linked against the wrong (static) library. If you want to use the - libcurl.dll and import lib, you do not need any extra CFLAGS, but use one of - the import libraries below. These are the libraries produced by the various - lib/Makefile.* files: - - Target: static lib. import lib for libcurl*.dll. - ----------------------------------------------------------- - MinGW: libcurl.a libcurldll.a - MSVC (release): libcurl.lib libcurl_imp.lib - MSVC (debug): libcurld.lib libcurld_imp.lib - Borland: libcurl.lib libcurl_imp.lib - - 5.8 libcurl.so.X: open failed: No such file or directory - - This is an error message you might get when you try to run a program linked - with a shared version of libcurl and your runtime linker (ld.so) could not - find the shared library named libcurl.so.X. (Where X is the number of the - current libcurl ABI, typically 3 or 4). - - You need to make sure that ld.so finds libcurl.so.X. You can do that - multiple ways, and it differs somewhat between different operating systems. - They are usually: - - * Add an option to the linker command line that specify the hard-coded path - the runtime linker should check for the lib (usually -R) - - * Set an environment variable (LD_LIBRARY_PATH for example) where ld.so - should check for libs - - * Adjust the system's config to check for libs in the directory where you have - put the library (like Linux's /etc/ld.so.conf) - - 'man ld.so' and 'man ld' will tell you more details - - 5.9 How does libcurl resolve hostnames? - - libcurl supports a large number of name resolve functions. One of them is - picked at build-time and will be used unconditionally. Thus, if you want to - change name resolver function you must rebuild libcurl and tell it to use a - different function. - - - The non-IPv6 resolver that can use one of four different hostname resolve - calls (depending on what your system supports): - - A - gethostbyname() - B - gethostbyname_r() with 3 arguments - C - gethostbyname_r() with 5 arguments - D - gethostbyname_r() with 6 arguments - - - The IPv6-resolver that uses getaddrinfo() - - - The c-ares based name resolver that uses the c-ares library for resolves. - Using this offers asynchronous name resolves. - - - The threaded resolver (default option on Windows). It uses: - - A - gethostbyname() on plain IPv4 hosts - B - getaddrinfo() on IPv6 enabled hosts - - Also note that libcurl never resolves or reverse-lookups addresses given as - pure numbers, such as 127.0.0.1 or ::1. - - 5.10 How do I prevent libcurl from writing the response to stdout? - - libcurl provides a default built-in write function that writes received data - to stdout. Set the CURLOPT_WRITEFUNCTION to receive the data, or possibly - set CURLOPT_WRITEDATA to a different FILE * handle. - - 5.11 How do I make libcurl not receive the whole HTTP response? - - You make the write callback (or progress callback) return an error and - libcurl will then abort the transfer. - - 5.12 Can I make libcurl fake or hide my real IP address? - - No. libcurl operates on a higher level. Besides, faking IP address would - imply sending IP packets with a made-up source address, and then you normally - get a problem with receiving the packet sent back as they would then not be - routed to you. - - If you use a proxy to access remote sites, the sites will not see your local - IP address but instead the address of the proxy. - - Also note that on many networks NATs or other IP-munging techniques are used - that makes you see and use a different IP address locally than what the - remote server will see you coming from. You may also consider using - https://www.torproject.org/ . - - 5.13 How do I stop an ongoing transfer? - - With the easy interface you make sure to return the correct error code from - one of the callbacks, but none of them are instant. There is no function you - can call from another thread or similar that will stop it immediately. - Instead, you need to make sure that one of the callbacks you use returns an - appropriate value that will stop the transfer. Suitable callbacks that you - can do this with include the progress callback, the read callback and the - write callback. - - If you are using the multi interface, you can also stop a transfer by - removing the particular easy handle from the multi stack at any moment you - think the transfer is done or when you wish to abort the transfer. - - 5.14 Using C++ non-static functions for callbacks? - - libcurl is a C library, it does not know anything about C++ member functions. - - You can overcome this "limitation" with relative ease using a static - member function that is passed a pointer to the class: - - // f is the pointer to your object. - static size_t YourClass::func(void *buffer, size_t sz, size_t n, void *f) - { - // Call non-static member function. - static_cast(f)->nonStaticFunction(); - } - - // This is how you pass pointer to the static function: - curl_easy_setopt(hcurl, CURLOPT_WRITEFUNCTION, YourClass::func); - curl_easy_setopt(hcurl, CURLOPT_WRITEDATA, this); - - 5.15 How do I get an FTP directory listing? - - If you end the FTP URL you request with a slash, libcurl will provide you - with a directory listing of that given directory. You can also set - CURLOPT_CUSTOMREQUEST to alter what exact listing command libcurl would use - to list the files. - - The follow-up question tends to be how is a program supposed to parse the - directory listing. How does it know what's a file and what's a directory and - what's a symlink etc. If the FTP server supports the MLSD command then it - will return data in a machine-readable format that can be parsed for type. - The types are specified by RFC 3659 section 7.5.1. If MLSD is not supported - then you have to work with what you are given. The LIST output format is - entirely at the server's own liking and the NLST output does not reveal any - types and in many cases does not even include all the directory entries. - Also, both LIST and NLST tend to hide Unix-style hidden files (those that - start with a dot) by default so you need to do "LIST -a" or similar to see - them. - - Example - List only directories. - ftp.funet.fi supports MLSD and ftp.kernel.org does not: - - curl -s ftp.funet.fi/pub/ -X MLSD | \ - perl -lne 'print if s/(?:^|;)type=dir;[^ ]+ (.+)$/$1/' - - curl -s ftp.kernel.org/pub/linux/kernel/ | \ - perl -lne 'print if s/^d[-rwx]{9}(?: +[^ ]+){7} (.+)$/$1/' - - If you need to parse LIST output in libcurl one such existing - list parser is available at https://cr.yp.to/ftpparse.html Versions of - libcurl since 7.21.0 also provide the ability to specify a wildcard to - download multiple files from one FTP directory. - - 5.16 I want a different time-out - - Sometimes users realize that CURLOPT_TIMEOUT and CURLOPT_CONNECTIMEOUT are - not sufficiently advanced or flexible to cover all the various use cases and - scenarios applications end up with. - - libcurl offers many more ways to time-out operations. A common alternative - is to use the CURLOPT_LOW_SPEED_LIMIT and CURLOPT_LOW_SPEED_TIME options to - specify the lowest possible speed to accept before to consider the transfer - timed out. - - The most flexible way is by writing your own time-out logic and using - CURLOPT_XFERINFOFUNCTION (perhaps in combination with other callbacks) and - use that to figure out exactly when the right condition is met when the - transfer should get stopped. - - 5.17 Can I write a server with libcurl? - - No. libcurl offers no functions or building blocks to build any kind of - Internet protocol server. libcurl is only a client-side library. For server - libraries, you need to continue your search elsewhere but there exist many - good open source ones out there for most protocols you could want a server - for. There are also really good stand-alone servers that have been tested - and proven for many years. There is no need for you to reinvent them. - - 5.18 Does libcurl use threads? - - Put simply: no, libcurl will execute in the same thread you call it in. All - callbacks will be called in the same thread as the one you call libcurl in. - - If you want to avoid your thread to be blocked by the libcurl call, you make - sure you use the non-blocking multi API which will do transfers - asynchronously - still in the same single thread. - - libcurl will potentially internally use threads for name resolving, if it - was built to work like that, but in those cases it will create the child - threads by itself and they will only be used and then killed internally by - libcurl and never exposed to the outside. - -6. License Issues - - curl and libcurl are released under an MIT/X derivative license. The license - is liberal and should not impose a problem for your project. This section is - just a brief summary for the cases we get the most questions. (Parts of this - section was much enhanced by Bjorn Reese.) - - We are not lawyers and this is not legal advice. You should probably consult - one if you want true and accurate legal insights without our prejudice. Note - especially that this section concerns the libcurl license only; compiling in - features of libcurl that depend on other libraries (e.g. OpenSSL) may affect - the licensing obligations of your application. - - 6.1 I have a GPL program, can I use the libcurl library? - - Yes - - Since libcurl may be distributed under the MIT/X derivative license, it can - be used together with GPL in any software. - - 6.2 I have a closed-source program, can I use the libcurl library? - - Yes - - libcurl does not put any restrictions on the program that uses the library. - - 6.3 I have a BSD licensed program, can I use the libcurl library? - - Yes - - libcurl does not put any restrictions on the program that uses the library. - - 6.4 I have a program that uses LGPL libraries, can I use libcurl? - - Yes - - The LGPL license does not clash with other licenses. - - 6.5 Can I modify curl/libcurl for my program and keep the changes secret? - - Yes - - The MIT/X derivative license practically allows you to do almost anything - with the sources, on the condition that the copyright texts in the sources - are left intact. - - 6.6 Can you please change the curl/libcurl license to XXXX? - - No. - - We have carefully picked this license after years of development and - discussions and a large amount of people have contributed with source code - knowing that this is the license we use. This license puts the restrictions - we want on curl/libcurl and it does not spread to other programs or - libraries that use it. It should be possible for everyone to use libcurl or - curl in their projects, no matter what license they already have in use. - - 6.7 What are my obligations when using libcurl in my commercial apps? - - Next to none. All you need to adhere to is the MIT-style license (stated in - the COPYING file) which basically says you have to include the copyright - notice in "all copies" and that you may not use the copyright holder's name - when promoting your software. - - You do not have to release any of your source code. - - You do not have to reveal or make public any changes to the libcurl source - code. - - You do not have to broadcast to the world that you are using libcurl within - your app. - - All we ask is that you disclose "the copyright notice and this permission - notice" somewhere. Most probably like in the documentation or in the section - where other third party dependencies already are mentioned and acknowledged. - - As can be seen here: https://curl.se/docs/companies.html and elsewhere, - more and more companies are discovering the power of libcurl and take - advantage of it even in commercial environments. - - -7. PHP/CURL Issues - - 7.1 What is PHP/CURL? - - The module for PHP that makes it possible for PHP programs to access curl- - functions from within PHP. - - In the cURL project we call this module PHP/CURL to differentiate it from - curl the command line tool and libcurl the library. The PHP team however - does not refer to it like this (for unknown reasons). They call it plain - CURL (often using all caps) or sometimes ext/curl, but both cause much - confusion to users which in turn gives us a higher question load. - - 7.2 Who wrote PHP/CURL? - - PHP/CURL was initially written by Sterling Hughes. - - 7.3 Can I perform multiple requests using the same handle? - - Yes - at least in PHP version 4.3.8 and later (this has been known to not - work in earlier versions, but the exact version when it started to work is - unknown to me). - - After a transfer, you just set new options in the handle and make another - transfer. This will make libcurl reuse the same connection if it can. - - 7.4 Does PHP/CURL have dependencies? - - PHP/CURL is a module that comes with the regular PHP package. It depends on - and uses libcurl, so you need to have libcurl installed properly before - PHP/CURL can be used. - -8. Development - - 8.1 Why does curl use C89? - - As with everything in curl, there is a history and we keep using what we have - used before until someone brings up the subject and argues for and works on - changing it. - - We started out using C89 in the 1990s because that was the only way to write - a truly portable C program and have it run as widely as possible. C89 was for - a long time even necessary to make things work on otherwise considered modern - platforms such as Windows. Today, we do not really know how many users that - still require the use of a C89 compiler. - - We will continue to use C89 for as long as nobody brings up a strong enough - reason for us to change our minds. The core developers of the project do not - feel restricted by this and we are not convinced that going C99 will offer us - enough of a benefit to warrant the risk of cutting off a share of users. - - 8.2 Will curl be rewritten? - - In one go: no. Little by little over time? Maybe. - - Over the years, new languages and clever operating environments come and go. - Every now and then the urge apparently arises to request that we rewrite curl - in another language. - - Some the most important properties in curl are maintaining the API and ABI - for libcurl and keeping the behavior for the command line tool. As long as we - can do that, everything else is up for discussion. To maintain the ABI, we - probably have to maintain a certain amount of code in C, and to remain rock - stable, we will never risk anything by rewriting a lot of things in one go. - That said, we can certainly offer more and more optional backends written in - other languages, as long as those backends can be plugged in at build-time. - Backends can be written in any language, but should probably provide APIs - usable from C to ease integration and transition. diff --git a/docs/FAQ.md b/docs/FAQ.md new file mode 100644 index 000000000000..0febe1b73ca6 --- /dev/null +++ b/docs/FAQ.md @@ -0,0 +1,1431 @@ + + +# Frequently Asked Questions + +# Philosophy + +## What is curl? + +curl is the name of the project. The name is a play on *Client for URLs*, +originally with URL spelled in uppercase to make it obvious it deals with +URLs. The fact it can also be read as *see URL* also helped, it works as an +abbreviation for *Client URL Request Library* or why not the recursive +version: *curl URL Request Library*. + +The curl project produces two products: + +### libcurl + +A client-side URL transfer library, supporting 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. + +libcurl supports HTTPS certificates, HTTP POST, HTTP PUT, FTP uploading, +Kerberos, SPNEGO, HTTP form based upload, proxies, cookies, user+password +authentication, file transfer resume, http proxy tunneling and more. + +libcurl is highly portable, it builds and works identically on numerous +platforms. The [internals document](https://curl.se/docs/install.html#Ports) +lists more than 110 operating systems and 28 CPU architectures on which curl +has been reported to run. + +libcurl is free, thread-safe, IPv6 compatible, feature rich, well supported +and fast. + +### curl + +A command line tool for getting or sending data using URL syntax. + +Since curl uses libcurl, curl supports the same wide range of common Internet +protocols that libcurl does. + +We pronounce curl with an initial k sound. It rhymes with words like girl and +earl. [This is a short WAV +file](https://media.merriam-webster.com/soundc11/c/curl0001.wav) to help you. + +There are numerous sub-projects and related projects that also use the word +curl in the project names in various combinations, but you should take notice +that this FAQ is directed at the command-line tool named curl (and libcurl the +library), and may therefore not be valid for other curl-related projects. +(There is however a small section for the PHP/CURL in this FAQ.) + +## What is libcurl? + +libcurl is a reliable and portable library for doing Internet data transfers +using one or more of its supported Internet protocols. + +You can use libcurl freely in your application, be it open source, commercial +or closed-source. + +libcurl is most probably the most portable, most powerful and most often used +C-based multi-platform file transfer library on this planet - be it open +source or commercial. + +## What is curl not? + +curl is not a Wget clone. That is a common misconception. Never, during curl's +development, have we intended curl to replace Wget or compete on its market. +curl is targeted at single-shot file transfers. + +curl is not a website mirroring program. If you want to use curl to mirror +something: fine, go ahead and write a script that wraps around curl or use +libcurl to make it reality. + +curl is not an FTP site mirroring program. Sure, get and send FTP with curl +but if you want systematic and sequential behavior you should write a script +(or write a new program that interfaces libcurl) and do it. + +curl is not a PHP tool, even though it works perfectly well when used from or +with PHP (when using the PHP/CURL module). + +curl is not a program for a single operating system. curl exists, compiles, +builds and runs under a wide range of operating systems, including all modern +Unixes (and a bunch of older ones too), Windows, Amiga, OS/2, macOS, QNX etc. + +## When will you make curl do ... ? + +We love suggestions of what to change in order to make curl and libcurl +better. We do however believe in a few rules when it comes to the future of +curl: + +curl the command line tool is to remain a non-graphical command line tool. If +you want GUIs or fancy scripting capabilities, you should look for another +tool that uses libcurl. + +We do not add things to curl that other small and available tools already do +well at the side. curl's output can be piped into another program or +redirected to another file for the next program to interpret. + +We focus on protocol related issues and improvements. If you want to do more +magic with the supported protocols than curl currently does, chances are good +we will agree. If you want to add more protocols, we may agree. + +If you want someone else to do all the work while you wait for us to implement +it for you, that is not a friendly attitude. We spend a considerable time +already on maintaining and developing curl. In order to get more out of us, +you should consider trading in some of your time and effort in return. Simply +go to the [GitHub repository](https://github.com/curl/curl), fork the project, +and create pull requests with your proposed changes. + +If you write the code, chances are better that it will get into curl faster. + +## Who makes curl? + +curl and libcurl are not made by any single individual. Daniel Stenberg is +project leader and main developer, but other persons' submissions are +important and crucial. Anyone can contribute and post their changes and +improvements and have them inserted in the main sources (of course on the +condition that developers agree that the fixes are good). + +The full list of all contributors is found in the docs/THANKS file. + +curl is developed by a community, with Daniel at the wheel. + +## What do you get for making curl? + +Project curl is entirely free and open. We do this voluntarily, mostly in our +spare time. Companies may pay individual developers to work on curl. This is +not controlled by nor supervised in any way by the curl project. + +We get help from companies. Haxx provides website, bandwidth, mailing lists +etc, GitHub hosts [the primary git repository](https://github.com/curl/curl) +and other services like the bug tracker. Also again, some companies have +sponsored certain parts of the development in the past and I hope some will +continue to do so in the future. + +If you want to [support our project](https://curl.se/sponsors.html), consider +a donation or a banner-program or even better: by helping us with coding, +documenting or testing etc. + +## What about CURL from curl.com? + +During the summer of 2001, curl.com was busy advertising their client-side +programming language for the web, named CURL. + +We are in no way associated with curl.com or their CURL programming language. + +Our project name curl has been in effective use since 1998. We were not the +first computer related project to use the name *curl* and do not claim any +rights to the name. + +We recognize that we will be living in parallel with curl.com and wish them +every success. + +## I have a problem, who do I mail? + +Please do not mail any single individual unless you really need to. Keep +curl-related questions on a suitable mailing list. All available mailing lists +are listed [online](https://curl.se/mail/). + +Keeping curl-related questions and discussions on mailing lists allows others +to join in and help, to share their ideas, to contribute their suggestions and +to spread their wisdom. Keeping discussions on public mailing lists also +allows for others to learn from this (both current and future users thanks to +the web based archives of the mailing lists), thus saving us from having to +repeat ourselves even more. Thanks for respecting this. + +If you have found or simply suspect a security problem in curl or libcurl, +submit all the details at [HackerOne](https://hackerone.com/curl). On there we +keep the issue private while we investigate, confirm it, work and validate a +fix and agree on a time schedule for publication etc. That way we produce a +fix in a timely manner before the flaw is announced to the world, reducing the +impact the problem risks having on existing users. + +Security issues can also be taking to the curl security team by emailing +security at curl.se (closed list of receivers, mails are not disclosed). + +## Where do I buy commercial support for curl? + +curl is fully open source. It means you can hire any skilled engineer to fix +your curl-related problems. + +We list [available alternatives](https://curl.se/support.html). + +## How many are using curl? + +It is impossible to tell. + +We do not know how many users that knowingly have installed and use curl. + +We do not know how many users that use curl without knowing that they are in +fact using it. + +We do not know how many users that downloaded or installed curl and then never +use it. + +In 2025, we estimate that curl runs in roughly thirty billion installations +world wide. + +## Why do you not update ca-bundle.crt + +In the curl project we have decided not to attempt to keep this file updated +(or even present) since deciding what to add to a ca cert bundle is an +undertaking we have not been ready to accept, and the one we can get from +Mozilla is perfectly fine so there is no need to duplicate that work. + +Today, with many services performed over HTTPS, every operating system should +come with a default ca cert bundle that can be deemed somewhat trustworthy and +that collection (if reasonably updated) should be deemed to be a lot better +than a private curl version. + +If you want the most recent collection of ca certs that Mozilla Firefox uses, +we recommend that using our online [CA certificate +service](https://curl.se/docs/caextract.html) setup for this purpose. + +## I have a problem who, can I chat with? + +There is a bunch of friendly people hanging out in the #curl channel on the +IRC network libera.chat. If you are polite and nice, chances are good that you +can get -- or provide -- help instantly. + +## curl's ECCN number? + +The US government restricts exports of software that contains or uses +cryptography. When doing so, the Export Control Classification Number (ECCN) +is used to identify the level of export control etc. + +Apache Software Foundation has [a good explanation of +ECCN](https://www.apache.org/dev/crypto.html). + +We believe curl's number might be ECCN 5D002, another possibility is 5D992. It +seems necessary to write them (the authority that administers ECCN numbers), +asking to confirm. + +Comprehensible explanations of the meaning of such numbers and how to obtain +them (resp.) are [here](https://www.bis.gov/licensing/classify-your-item) +and [here](https://www.bis.gov/licensing/classify-your-item/publicly-available-classification-information). + +An incomprehensible description of the two numbers above is available on +[bis.doc.gov](https://www.bis.doc.gov/index.php/documents/new-encryption/1653-ccl5-pt2-3) + +## How do I submit my patch? + +We strongly encourage you to submit changes and improvements directly as [pull +requests on GitHub](https://github.com/curl/curl/pulls). + +If you for any reason cannot or will not deal with GitHub, send your patch to +the curl-library mailing list. We are many subscribers there and there are +lots of people who can review patches, comment on them and receive them +properly. + +Lots of more details are found in the +[contribute](https://curl.se/dev/contribute.html) and +[internals](https://curl.se/dev/internals.html) +documents. + +## How do I port libcurl to my OS? + +Here's a rough step-by-step: + +1. copy a suitable lib/config-*.h file as a start to `lib/config-[youros].h` +2. edit `lib/config-[youros].h` to match your OS and setup +3. edit `lib/curl_setup.h` to include `config-[youros].h` when your OS is + detected by the preprocessor, in the style others already exist +4. compile `lib/*.c` and make them into a library + +# Install + +## configure fails when using static libraries + +You may find that configure fails to properly detect the entire dependency +chain of libraries when you provide static versions of the libraries that +configure checks for. + +The reason why static libraries is much harder to deal with is that for them +we do not get any help but the script itself must know or check what more +libraries that are needed (with shared libraries, that dependency chain is +handled automatically). This is an error-prone process and one that also tends +to vary over time depending on the release versions of the involved components +and may also differ between operating systems. + +For that reason, configure does few attempts to actually figure this out and +you are instead encouraged to set `LIBS` and `LDFLAGS` accordingly when you invoke +configure, and point out the needed libraries and set the necessary flags +yourself. + +## Does curl work with other SSL libraries? + +curl has been written to use a generic SSL function layer internally, and +that SSL functionality can then be provided by one out of many different SSL +backends. + +curl can be built to use one of the following SSL alternatives: OpenSSL, +LibreSSL, BoringSSL, AWS-LC, GnuTLS, wolfSSL, mbedTLS, Schannel (native +Windows) or Rustls. They all have their pros and cons, and we maintain [a TLS +library comparison](https://curl.se/docs/ssl-compared.html). + +## How do I upgrade curl.exe in Windows? + +The curl tool that is shipped as an integrated component of Windows 10 and +Windows 11 is managed by Microsoft. If you were to delete the file or replace +it with a newer version downloaded from [the curl +website](https://curl.se/windows/), then Windows Update will cease to work on +your system. + +There is no way to independently force an upgrade of the curl.exe that is part +of Windows other than through the regular Windows update process. There is +also nothing the curl project itself can do about this, since this is managed +and controlled entirely by Microsoft as owners of the operating system. + +You can always download and install [the latest version of curl for +Windows](https://curl.se/windows/) into a separate location. + +## Does curl support SOCKS (RFC 1928) ? + +Yes, SOCKS 4 and 5 are supported. + +# Usage + +## curl: (1) SSL is disabled, https: not supported + +If you get this output when trying to get anything from an HTTPS server, it +means that the instance of curl/libcurl that you are using was built without +support for this protocol. + +This could have happened if the configure script that was run at build time +could not find all libs and include files curl requires for SSL to work. If +the configure script fails to find them, curl is simply built without SSL +support. + +To get HTTPS support into a curl that was previously built but that reports +that HTTPS is not supported, you should dig through the document and logs and +check out why the configure script does not find the SSL libs and/or include +files. + +## How do I tell curl to resume a transfer? + +curl supports resumed transfers both ways on both FTP and HTTP. Try the `-C` +option. + +## Why does my posting using -F not work? + +You cannot arbitrarily use `-F` or `-d`, the choice between `-F` or `-d` +depends on the HTTP operation you need curl to do and what the web server that +will receive your post expects. + +If the form you are trying to submit uses the type 'multipart/form-data', +then and only then you must use the -F type. In all the most common cases, +you should use `-d` which then causes a posting with the type +`application/x-www-form-urlencoded`. + +This is described in some detail in the +[Manual](https://curl.se/docs/tutorial.html) and [The Art Of HTTP +Scripting](https://curl.se/docs/httpscripting.html) documents, and if you do +not understand it the first time, read it again before you post questions +about this to the mailing list. Also, try reading through the mailing list +archives for old postings and questions regarding this. + +## How do I tell curl to run custom FTP commands? + +You can tell curl to perform optional commands both before and/or after a file +transfer. Study the `-Q`/`--quote` option. + +Since curl is used for file transfers, you do not normally use curl to perform +FTP commands without transferring anything. Therefore you must always specify +a URL to transfer to/from even when doing custom FTP commands, or use `-I` +which implies the *no body*" option sent to libcurl. + +## How can I disable the Accept: header? + +You can change this and all internally generated headers by adding a +replacement with the `-H`/`--header` option. By adding a header with empty +contents you safely disable that one. Use `-H Accept:` to disable that +specific header. + +## Does curl support ASP, XML, XHTML or HTML version Y? + +To curl, all contents are alike. It does not matter how the page was +generated. It may be ASP, PHP, Perl, shell-script, SSI or plain HTML +files. There is no difference to curl and it does not even know what kind of +language that generated the page. + +See also the separate question about JavaScript. + +## Can I use curl to delete/rename a file through FTP? + +Yes. You specify custom FTP commands with `-Q`/`--quote`. + +One example would be to delete a file after you have downloaded it: + + curl -O ftp://example.com/coolfile -Q '-DELE coolfile' + +or rename a file after upload: + + curl -T infile ftp://example.com/dir/ -Q "-RNFR infile" -Q "-RNTO newname" + +## How do I tell curl to follow HTTP redirects? + +curl does not follow so-called redirects by default. The `Location:` header that +informs the client about this is only interpreted if you are using the +`-L`/`--location` option. As in: + + curl -L https://example.com + +Not all redirects are HTTP ones. See [Redirects work in browser but not with +curl](#redirects-work-in-browser-but-not-with-curl) + +## How do I use curl in my favorite programming language? + +Many programming languages have interfaces and bindings that allow you to use +curl without having to use the command line tool. If you are fluent in such a +language, you may prefer to use one of these interfaces instead. + +Find out more about which languages that support curl directly, and how to +install and use them, in the [libcurl section of the curl +website](https://curl.se/libcurl/). + +All the various bindings to libcurl are made by other projects and people, +outside of the curl project. The curl project itself only produces libcurl +with its plain C API. If you do not find anywhere else to ask you can ask +about bindings on the curl-library list too, but be prepared that people on +that list may not know anything about bindings. + +In December 2025 there were around **60** different [interfaces +available](https://curl.se/libcurl/bindings.html) for just about all the +languages you can imagine. + +## What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP? + +curl adheres to the HTTP spec, which basically means you can play with *any* +protocol that is built on top of HTTP. Protocols such as SOAP, WebDAV and +XML-RPC are all such ones. You can use `-X` to set custom requests and -H to +set custom headers (or replace internally generated ones). + +Using libcurl is of course just as good and you would just use the proper +library options to do the same. + +## How do I POST with a different Content-Type? + +You can always replace the internally generated headers with `-H`/`--header`. +To make a simple HTTP POST with `text/xml` as content-type, do something like: + + curl -d "datatopost" -H "Content-Type: text/xml" [URL] + +## Why do FTP-specific features over HTTP proxy fail? + +Because when you use an HTTP proxy, the protocol spoken on the network will be +HTTP, even if you specify an FTP URL. This effectively means that you normally +cannot use FTP-specific features such as FTP upload and FTP quote etc. + +There is one exception to this rule, and that is if you can *tunnel through* +the given HTTP proxy. Proxy tunneling is enabled with a special option (`-p`) +and is generally not available as proxy admins usually disable tunneling to +ports other than 443 (which is used for HTTPS access through proxies). + +## Why do my single/double quotes fail? + +To specify a command line option that includes spaces, you might need to put +the entire option within quotes. Like in: + + curl -d " with spaces " example.com + +or perhaps + + curl -d ' with spaces ' example.com + +Exactly what kind of quotes and how to do this is entirely up to the shell or +command line interpreter that you are using. For most Unix shells, you can +more or less pick either single (`'`) or double (`"`) quotes. For Windows/DOS +command prompts you must use double (") quotes, and if the option string +contains inner double quotes you can escape them with a backslash. + +For Windows PowerShell the arguments are not always passed on as expected +because curl is not a PowerShell script. You may or may not be able to use +single quotes. To escape inner double quotes seems to require a +backslash-backtick escape sequence and the outer quotes as double quotes. + +Please study the documentation for your particular environment. Examples in +the curl docs will use a mix of both of these as shown above. You must adjust +them to work in your environment. + +Remember that curl works and runs on more operating systems than most single +individuals have ever tried. + +## Does curl support JavaScript or PAC (automated proxy config)? + +Many webpages do magic stuff using embedded JavaScript. curl and libcurl have +no built-in support for that, so it will be treated just like any other +contents. + +`.pac` files are a Netscape invention and are sometimes used by organizations +to allow them to differentiate which proxies to use. The `.pac` contents is +just a JavaScript program that gets invoked by the browser and that returns +the name of the proxy to connect to. Since curl does not support JavaScript, +it cannot support .pac proxy configuration either. + +Some workarounds usually suggested to overcome this JavaScript dependency: + +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. + +## Can I do recursive fetches with curl? + +No. curl itself has no code that performs recursive operations, such as those +performed by Wget and similar tools. + +There exists curl using scripts with that functionality, and you can write +programs based on libcurl to do it, but the command line tool curl itself +cannot. + +## What certificates do I need when I use SSL? + +There are three different kinds of certificates to keep track of when we talk +about using SSL-based protocols (HTTPS or FTPS) using curl or libcurl. + +### Client certificate + +The server you communicate with may require that you can provide this in +order to prove that you actually are who you claim to be. If the server +does not require this, you do not need a client certificate. + +A client certificate is always used together with a private key, and the +private key has a passphrase that protects it. + +### Server certificate + +The server you communicate with has a server certificate. You can and should +verify this certificate to make sure that you are truly talking to the real +server and not a server impersonating it. + +Servers often also provide an intermediate certificate. It acts as a bridge +between a website's SSL certificate and a Certificate Authority's (CA) root +certificate, creating a "chain of trust". + +### Certificate Authority Certificate ("CA cert") + +You often have several CA certs in a CA cert bundle that can be used to verify +a server certificate that was signed by one of the authorities in the bundle. +curl does not come with a CA cert bundle but most curl installs provide one. +You can also override the default. + +Server certificate verification is enabled by default in curl and libcurl. +Server certificates that are *self-signed* or otherwise signed by a CA that +you do not have a CA cert for, cannot be verified. If the verification during +a connect fails, you are refused access. You then might have to explicitly +disable the verification to connect to the server. + +## How do I list the root directory of an FTP server? + +There are two ways. The way defined in the RFC is to use an encoded slash in +the first path part. List the `/tmp` directory like this: + + curl ftp://ftp.example.com/%2ftmp/ + +or the not-quite-kosher-but-more-readable way, by simply starting the path +section of the URL with a slash: + + curl ftp://ftp.example.com//tmp/ + +## Can I use curl to send a POST/PUT and not wait for a response? + +No. + +You can easily write your own program using libcurl to do such stunts. + +## How do I get HTTP from a host using a specific IP address? + +For example, you may be trying out a website installation that is not yet in +the DNS. Or you have a site using multiple IP addresses for a given host +name and you want to address a specific one out of the set. + +Set a custom `Host:` header that identifies the server name you want to reach +but use the target IP address in the URL: + + curl --header "Host: www.example.com" https://somewhere.example/ + +You can also opt to add faked hostname entries to curl with the --resolve +option. That has the added benefit that things like redirects will also work +properly. The above operation would instead be done as: + + curl --resolve www.example.com:80:127.0.0.1 https://www.example.com/ + +## How to SFTP from my user's home directory? + +Contrary to how FTP works, SFTP and SCP URLs specify the exact directory to +work with. It means that if you do not specify that you want the user's home +directory, you get the actual root directory. + +To specify a file in your user's home directory, you need to use the correct +URL syntax which for SFTP might look similar to: + + curl -O -u user:password sftp://example.com/~/file.txt + +and for SCP it is just a different protocol prefix: + + curl -O -u user:password scp://example.com/~/file.txt + +## Protocol xxx not supported or disabled in libcurl + +When passing on a URL to curl to use, it may respond that the particular +protocol is not supported or disabled. The particular way this error message +is phrased is because curl does not make a distinction internally of whether a +particular protocol is not supported (i.e. never got any code added that knows +how to speak that protocol) or if it was explicitly disabled. curl can be +built to only support a given set of protocols, and the rest would then be +disabled or not supported. + +Note that this error will also occur if you pass a wrongly spelled protocol +part as in `htpts://example.com` or as in the less evident case if you prefix +the protocol part with a space as in `" https://example.com/"`. + +## curl `-X` gives me HTTP problems + +In normal circumstances, `-X` should hardly ever be used. + +By default you use curl without explicitly saying which request method to use +when the URL identifies an HTTP transfer. If you just pass in a URL like `curl +https://example.com` it will use GET. If you use `-d` or `-F`, curl will use +POST, `-I` will cause a HEAD and `-T` will make it a PUT. + +If for whatever reason you are not happy with these default choices that curl +does for you, you can override those request methods by specifying `-X +[WHATEVER]`. This way you can for example send a DELETE by doing +`curl -X DELETE [URL]`. + +It is thus pointless to do `curl -XGET [URL]` as GET would be used anyway. In +the same vein it is pointless to do `curl -X POST -d data [URL`. You can make +a fun and somewhat rare request that sends a request-body in a GET request +with something like `curl -X GET -d data [URL]`. + +Note that `-X` does not actually change curl's behavior as it only modifies +the actual string sent in the request, but that may of course trigger a +different set of events. + +Accordingly, by using `-XPOST` on a command line that for example would follow +a 303 redirect, you will effectively prevent curl from behaving correctly. Be +aware. + +# Running + +## Why do I get problems when I use & or % in the URL? + +In general Unix shells, the & symbol is treated specially and when used, it +runs the specified command in the background. To safely send the & as a part +of a URL, you should quote the entire URL by using single (`'`) or double +(`"`) quotes around it. Similar problems can also occur on some shells with +other characters, including ?*!$~(){}<>\|;`. When in doubt, quote the URL. + +An example that would invoke a remote CGI that uses &-symbols could be: + + curl 'https://www.example.com/cgi-bin/query?text=yes&q=curl' + +In Windows, the standard DOS shell treats the percent sign specially and you +need to use TWO percent signs for each single one you want to use in the URL. + +If you want a literal percent sign to be part of the data you pass in a POST +using `-d`/`--data` you must encode it as `%25` (which then also needs the +percent sign doubled on Windows machines). + +## How can I use {, }, [ or ] to specify multiple URLs? + +Because those letters have a special meaning to the shell, to be used in a URL +specified to curl you must quote them. + +An example that downloads two URLs (sequentially) would be: + + curl '{curl,www}.haxx.se' + +To be able to use those characters as actual parts of the URL (without using +them for the curl URL *globbing* system), use the `-g`/`--globoff` option: + + curl -g 'www.example.com/weirdname[].html' + +## Why do I get downloaded data even though the webpage does not exist? + +curl asks remote servers for the page you specify. If the page does not exist +at the server, the HTTP protocol defines how the server should respond and +that means that headers and a page will be returned. That is simply how HTTP +works. + +By using the `--fail` option you can tell curl explicitly to not get any data +if the HTTP return code does not say success. + +## Why do I get return code XXX from an HTTP server? + +RFC 2616 clearly explains the return codes. This is a short transcript. Go +read the RFC for exact details: + +### 400 Bad Request + +The request could not be understood by the server due to malformed +syntax. The client SHOULD NOT repeat the request without modifications. + +### 401 Unauthorized + +The request requires user authentication. + +### 403 Forbidden + +The server understood the request, but is refusing to fulfill it. +Authorization will not help and the request SHOULD NOT be repeated. + +### 404 Not Found + +The server has not found anything matching the Request-URI. No indication is +given as to whether the condition is temporary or permanent. + +### 405 Method Not Allowed + +The method specified in the Request-Line is not allowed for the resource +identified by the Request-URI. The response MUST include an `Allow:` header +containing a list of valid methods for the requested resource. + +### 301 Moved Permanently + +If you get this return code and an HTML output similar to this: + +

Moved Permanently

The document has moved here. + +it might be because you requested a directory URL but without the trailing +slash. Try the same operation again _with_ the trailing URL, or use the +`-L`/`--location` option to follow the redirection. + +## Can you tell me what error code 142 means? + +All curl error codes are described at the end of the man page, in the section +called **EXIT CODES**. + +Error codes that are larger than the highest documented error code means that +curl has exited due to a crash. This is a serious error, and we appreciate a +detailed bug report from you that describes how we could go ahead and repeat +this. + +## How do I keep usernames and passwords secret in curl command lines? + +This problem has two sides: + +The first part is to avoid having clear-text passwords in the command line so +that they do not appear in *ps* outputs and similar. That is easily avoided by +using the `-K` option to tell curl to read parameters from a file or stdin to +which you can pass the secret info. curl itself will also attempt to hide the +given password by blanking out the option - this does not work on all +platforms. + +To keep the passwords in your account secret from the rest of the world is +not a task that curl addresses. You could of course encrypt them somehow to +at least hide them from being read by human eyes, but that is not what +anyone would call security. + +Also note that regular HTTP (using Basic authentication) and FTP passwords are +sent as cleartext across the network. All it takes for anyone to fetch them is +to listen on the network. Eavesdropping is easy. Use more secure +authentication methods (like Digest, Negotiate or even NTLM) or consider the +SSL-based alternatives HTTPS and FTPS. + +## I found a bug + +It is not a bug if the behavior is documented. Read the docs first. Especially +check out the KNOWN_BUGS file, it may be a documented bug. + +If it is a problem with a binary you have downloaded or a package for your +particular platform, try contacting the person who built the package/archive +you have. + +If there is a bug, read the BUGS document first. Then report it as described +in there. + +## curl cannot authenticate to a server that requires NTLM? + +NTLM support requires OpenSSL, GnuTLS, mbedTLS or Microsoft Windows libraries +at build-time to provide this functionality. + +## My HTTP request using HEAD, PUT or DELETE does not work + +Many web servers allow or demand that the administrator configures the server +properly for these requests to work on the web server. + +Some servers seem to support HEAD only on certain kinds of URLs. + +To fully grasp this, try the documentation for the particular server software +you are trying to interact with. This is not anything curl can do anything +about. + +## Why do my HTTP range requests return the full document? + +Because the range may not be supported by the server, or the server may choose +to ignore it and return the full document anyway. + +## Why do I get "certificate verify failed" ? + +When you invoke curl and get an error 60 error back it means that curl could +not verify that the server's certificate was good. curl verifies the +certificate using the CA cert bundle and verifying for which names the +certificate has been granted. + +To completely disable the certificate verification, use `-k`. This does +however enable man-in-the-middle attacks and makes the transfer **insecure**. +We strongly advise against doing this for more than experiments. + +If you get this failure with a CA cert bundle installed and used, the server's +certificate might not be signed by one of the certificate authorities in your +CA store. It might for example be self-signed. You then correct this problem +by obtaining a valid CA cert for the server. Or again, decrease the security +by disabling this check. + +At times, you find that the verification works in your favorite browser but +fails in curl. When this happens, the reason is usually that the server sends +an incomplete cert chain. The server is mandated to send all *intermediate +certificates* but does not. This typically works with browsers anyway since +they A) cache such certs and B) supports AIA which downloads such missing +certificates on demand. This is a bad server configuration. A good way to +figure out if this is the case it to use [the SSL Labs +server](https://www.ssllabs.com/ssltest/) test and check the certificate +chain. + +Details are also in [the SSL certificates +document](https://curl.se/docs/sslcerts.html). + +## Why is curl -R on Windows one hour off? + +Since curl 7.53.0 this issue should be fixed as long as curl was built with +any modern compiler that allows for a 64-bit curl_off_t type. For older +compilers or prior curl versions it may set a time that appears one hour off. +This happens due to a flaw in how Windows stores and uses file modification +times and it is not easily worked around. For more details [read +this](https://www.codeproject.com/articles/Beating-the-Daylight-Savings-Time-Bug-and-Getting#comments-section). + +## Redirects work in browser but not with curl + +curl supports HTTP redirects well (see a previous question above). Browsers +generally support at least two other ways to perform redirects that curl does +not: + +Meta tags. You can write an HTML tag that will cause the browser to redirect +to another given URL after a certain time. + +JavaScript. You can write a JavaScript program embedded in an HTML page that +redirects the browser to another given URL. + +There is no way to make curl follow these redirects. You must either manually +figure out what the page is set to do, or write a script that parses the +results and fetches the new URL. + +## FTPS does not work + +curl supports FTPS (sometimes known as FTP-SSL) both implicit and explicit +mode. + +When a URL is used that starts with `FTPS://`, curl assumes implicit SSL on +the control connection and will therefore immediately connect and try to speak +SSL. `FTPS://` connections default to port 990. + +To use explicit FTPS, you use an `FTP://` URL and the `--ssl-reqd` option (or +one of its related flavors). This is the most common method, and the one +mandated by RFC 4217. This kind of connection will then of course use the +standard FTP port 21 by default. + +## My HTTP POST or PUT requests are slow + +libcurl makes all POST and PUT requests (except for requests with a small +request body) use the `Expect: 100-continue` header. This header allows the +server to deny the operation early so that libcurl can bail out before having +to send any data. This is useful in authentication cases and others. + +However, many servers do not implement the `Expect:` stuff properly and if the +server does not respond (positively) within 1 second libcurl will continue and +send off the data anyway. + +You can disable libcurl's use of the `Expect:` header the same way you disable +any header, using `-H` / `CURLOPT_HTTPHEADER`, or by forcing it to use HTTP +1.0. + +## Non-functional connect timeouts + +In most Windows setups having a timeout longer than 21 seconds make no +difference, as it will only send 3 TCP SYN packets and no more. The second +packet sent three seconds after the first and the third six seconds after +the second. No more than three packets are sent, no matter how long the +timeout is set. + +See option `TcpMaxConnectRetransmissions` on [this +page](https://support.microsoft.com/topic/hotfix-enables-the-configuration-of-the-tcp-maximum-syn-retransmission-amount-in-windows-7-or-windows-server-2008-r2-1b6f8352-2c5f-58bb-ead7-2cf021407c8e). + +Also, even on non-Windows systems there may run a firewall or anti-virus +software or similar that accepts the connection but does not actually do +anything else. This will make (lib)curl to consider the connection connected +and thus the connect timeout will not trigger. + +## file:// URLs containing drive letters (Windows, NetWare) + +When using curl to try to download a local file, one might use a URL in this +format: + + file://D:/blah.txt + +you will find that even if `D:\blah.txt` does exist, curl returns a 'file not +found' error. + +According to [RFC 1738](https://datatracker.ietf.org/doc/html/rfc1738), +`file://` URLs must contain a host component, but it is ignored by most +implementations. In the above example, `D:` is treated as the host component, +and is taken away. Thus, curl tries to open `/blah.txt`. If your system is +installed to drive C:, that will resolve to `C:\blah.txt`, and if that does +not exist you will get the not found error. + +To fix this problem, use `file://` URLs with *three* leading slashes: + + file:///D:/blah.txt + +Alternatively, if it makes more sense, specify `localhost` as the host +component: + + file://localhost/D:/blah.txt + +In either case, curl should now be looking for the correct file. + +## Why does not curl return an error when the network cable is unplugged? + +Unplugging a cable is not an error situation. The TCP/IP protocol stack was +designed to be fault tolerant, so even though there may be a physical break +somewhere the connection should not be affected, just possibly delayed. +Eventually, the physical break will be fixed or the data will be re-routed +around the physical problem through another path. + +In such cases, the TCP/IP stack is responsible for detecting when the network +connection is irrevocably lost. Since with some protocols it is perfectly +legal for the client to wait indefinitely for data, the stack may never report +a problem, and even when it does, it can take up to 20 minutes for it to +detect an issue. The curl option `--keepalive-time` enables keep-alive support +in the TCP/IP stack which makes it periodically probe the connection to make +sure it is still available to send data. That should reliably detect any +TCP/IP network failure. + +TCP keep alive will not detect the network going down before the TCP/IP +connection is established (e.g. during a DNS lookup) or using protocols that +do not use TCP. To handle those situations, curl offers a number of timeouts +on its own. `--speed-limit`/`--speed-time` will abort if the data transfer +rate falls too low, and `--connect-timeout` and `--max-time` can be used to +put an overall timeout on the connection phase or the entire transfer. + +A libcurl-using application running in a known physical environment (e.g. an +embedded device with only a single network connection) may want to act +immediately if its lone network connection goes down. That can be achieved by +having the application monitor the network connection on its own using an +OS-specific mechanism, then signaling libcurl to abort. + +## curl does not return error for HTTP non-200 responses + +Correct. Unless you use `-f` (`--fail`) or `--fail-with-body`. + +When doing HTTP transfers, curl will perform exactly what you are asking it to +do and if successful it will not return an error. You can use curl to test +your web server's "file not found" page (that gets 404 back), you can use it +to check your authentication protected webpages (that gets a 401 back) and so +on. + +The specific HTTP response code does not constitute a problem or error for +curl. It simply sends and delivers HTTP as you asked and if that worked, +everything is fine and dandy. The response code is generally providing more +higher level error information that curl does not care about. The error was +not in the HTTP transfer. + +If you want your command line to treat error codes in the 400 and up range as +errors and thus return a non-zero value and possibly show an error message, +curl has a dedicated option for that: `-f` (`CURLOPT_FAILONERROR` in libcurl +speak). + +You can also use the `-w` option and the variable `%{response_code}` to +extract the exact response code that was returned in the response. + +# libcurl + +## Is libcurl thread-safe? + +Yes. + +We have written the libcurl code specifically adjusted for multi-threaded +programs. libcurl will use thread-safe functions instead of non-safe ones if +your system has such. Note that you must never share the same handle in +multiple threads. + +There may be some exceptions to thread safety depending on how libcurl was +built. Please review [the guidelines for thread +safety](https://curl.se/libcurl/c/threadsafe.html) to learn more. + +## How can I receive all data into a large memory chunk? + +(See the [get in memory](https://curl.se/libcurl/c/getinmemory.html) example.) + +You are in full control of the callback function that gets called every time +there is data received from the remote server. You can make that callback do +whatever you want. You do not have to write the received data to a file. + +One solution to this problem could be to have a pointer to a struct that you +pass to the callback function. You set the pointer using the CURLOPT_WRITEDATA +option. Then that pointer will be passed to the callback instead of a FILE * +to a file: + +~~~c +/* store data this struct */ +struct MemoryStruct { + char *memory; + size_t size; +}; + +/* imaginary callback function */ +size_t +WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data) +{ + size_t realsize = size * nmemb; + struct MemoryStruct *mem = (struct MemoryStruct *)data; + + mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1); + if(mem->memory) { + memcpy(&(mem->memory[mem->size]), ptr, realsize); + mem->size += realsize; + mem->memory[mem->size] = 0; + } + return realsize; +} +~~~ + +## How do I fetch multiple files with libcurl? + +libcurl has excellent support for transferring multiple files. You should just +repeatedly set new URLs with `curl_easy_setopt()` and then transfer it with +`curl_easy_perform()`. The handle you get from curl_easy_init() is not only +reusable, but you are even encouraged to reuse it if you can, as that will +enable libcurl to use persistent connections. + +## Does libcurl do Winsock initialization on Win32 systems? + +Yes, if told to in the `curl_global_init()` call. + +## Does CURLOPT_WRITEDATA and CURLOPT_READDATA work on Win32 ? + +Yes, but you cannot open a FILE * and pass the pointer to a DLL and have that +DLL use the FILE * (as the DLL and the client application cannot access each +others' variable memory areas). If you set `CURLOPT_WRITEDATA` you must also use +`CURLOPT_WRITEFUNCTION` as well to set a function that writes the file, even if +that simply writes the data to the specified FILE *. Similarly, if you use +`CURLOPT_READDATA` you must also specify `CURLOPT_READFUNCTION`. + +## What about Keep-Alive or persistent connections? + +curl and libcurl have excellent support for persistent connections when +transferring several files from the same server. curl will attempt to reuse +connections for all URLs specified on the same command line/config file, and +libcurl will reuse connections for all transfers that are made using the same +libcurl handle. + +When you use the easy interface the connection cache is kept within the easy +handle. If you instead use the multi interface, the connection cache will be +kept within the multi handle and will be shared among all the easy handles +that are used within the same multi handle. + +## Link errors when building libcurl on Windows + +You need to make sure that your project, and all the libraries (both static +and dynamic) that it links against, are compiled/linked against the same run +time library. + +This is determined by the `/MD`, `/ML`, `/MT` (and their corresponding `/M?d`) +options to the command line compiler. `/MD` (linking against `MSVCRT.dll`) +seems to be the most commonly used option. + +When building an application that uses the static libcurl library, you must +add `-DCURL_STATICLIB` to your `CFLAGS`. Otherwise the linker will look for +dynamic import symbols. If you are using Visual Studio, you need to instead +add `CURL_STATICLIB` in the "Preprocessor Definitions" section. + +If you get a linker error like `unknown symbol __imp__curl_easy_init ...` you +have linked against the wrong (static) library. If you want to use the +libcurl.dll and import lib, you do not need any extra `CFLAGS`, but use one of +the import libraries below. These are the libraries produced by the various +lib/Makefile.* files: + +| Target | static lib | import lib for DLL | +|----------------|----------------|--------------------| +| MinGW | `libcurl.a` | `libcurldll.a` | +| MSVC (release) | `libcurl.lib` | `libcurl_imp.lib` | +| MSVC (debug) | `libcurld.lib` | `libcurld_imp.lib` | + +## libcurl.so.X: open failed: No such file or directory + +This is an error message you might get when you try to run a program linked +with a shared version of libcurl and your runtime linker (`ld.so`) could not +find the shared library named `libcurl.so.X`. (Where X is the number of the +current libcurl ABI, typically 3 or 4). + +You need to make sure that `ld.so` finds `libcurl.so.X`. You can do that +multiple ways, and it differs somewhat between different operating systems. +They are usually: + +* Add an option to the linker command line that specify the hard-coded path + the runtime linker should check for the lib (usually `-R`) +* Set an environment variable (`LD_LIBRARY_PATH` for example) where `ld.so` + should check for libs +* Adjust the system's config to check for libs in the directory where you have + put the library (like Linux's `/etc/ld.so.conf`) + +`man ld.so` and`'man ld` will tell you more details + +## How does libcurl resolve hostnames? + +libcurl supports a large number of name resolve functions. One of them is +picked at build-time and will be used unconditionally. Thus, if you want to +change name resolver function you must rebuild libcurl and tell it to use a +different function. + +### The non-IPv6 resolver + +The non-IPv6 resolver that can use one of four different hostname resolve +calls depending on what your system supports: + +1. gethostbyname() +2. gethostbyname_r() with 3 arguments +3. gethostbyname_r() with 5 arguments +4. gethostbyname_r() with 6 arguments + +### The IPv6 resolver + +Uses getaddrinfo() + +### The cares resolver + +The c-ares based name resolver that uses the c-ares library for resolves. +Using this offers asynchronous name resolves. + +## The threaded resolver + +It uses the IPv6 or the non-IPv6 resolver solution in a temporary thread. + +## How do I prevent libcurl from writing the response to stdout? + +libcurl provides a default built-in write function that writes received data +to stdout. Set the `CURLOPT_WRITEFUNCTION` to receive the data, or possibly +set `CURLOPT_WRITEDATA` to a different FILE * handle. + +## How do I make libcurl not receive the whole HTTP response? + +You make the write callback (or progress callback) return an error and libcurl +will then abort the transfer. + +## Can I make libcurl fake or hide my real IP address? + +No. libcurl operates on a higher level. Besides, faking IP address would +imply sending IP packets with a made-up source address, and then you normally +get a problem with receiving the packet sent back as they would then not be +routed to you. + +If you use a proxy to access remote sites, the sites will not see your local +IP address but instead the address of the proxy. + +Also note that on many networks NATs or other IP-munging techniques are used +that makes you see and use a different IP address locally than what the remote +server will see you coming from. You may also consider using +[Tor](https://www.torproject.org/). + +## How do I stop an ongoing transfer? + +With the easy interface you make sure to return the correct error code from +one of the callbacks, but none of them are instant. There is no function you +can call from another thread or similar that will stop it immediately. +Instead, you need to make sure that one of the callbacks you use returns an +appropriate value that will stop the transfer. Suitable callbacks that you can +do this with include the progress callback, the read callback and the write +callback. + +If you are using the multi interface, you can also stop a transfer by removing +the particular easy handle from the multi stack at any moment you think the +transfer is done or when you wish to abort the transfer. + +## Using C++ non-static functions for callbacks? + +libcurl is a C library, it does not know anything about C++ member functions. + +You can overcome this limitation with relative ease using a static member +function that is passed a pointer to the class: + +~~~c++ +// f is the pointer to your object. +static size_t YourClass::func(void *buffer, size_t sz, size_t n, void *f) +{ + // Call non-static member function. + static_cast(f)->nonStaticFunction(); +} + +// This is how you pass pointer to the static function: +curl_easy_setopt(hcurl, CURLOPT_WRITEFUNCTION, YourClass::func); +curl_easy_setopt(hcurl, CURLOPT_WRITEDATA, this); +~~~ + +## How do I get an FTP directory listing? + +If you end the FTP URL you request with a slash, libcurl will provide you with +a directory listing of that given directory. You can also set +`CURLOPT_CUSTOMREQUEST` to alter what exact listing command libcurl would use +to list the files. + +The follow-up question tends to be how is a program supposed to parse the +directory listing. How does it know what's a file and what's a directory and +what's a symlink etc. If the FTP server supports the `MLSD` command then it +will return data in a machine-readable format that can be parsed for type. The +types are specified by RFC 3659 section 7.5.1. If `MLSD` is not supported then +you have to work with what you are given. The `LIST` output format is entirely +at the server's own liking and the `NLST` output does not reveal any types and +in many cases does not even include all the directory entries. Also, both +`LIST` and `NLST` tend to hide Unix-style hidden files (those that start with +a dot) by default so you need to do `LIST -a` or similar to see them. + +Example - List only directories. `ftp.funet.fi` supports `MLSD` and +`ftp.kernel.org` does not: + + curl -s ftp.funet.fi/pub/ -X MLSD | \ + perl -lne 'print if s/(?:^|;)type=dir;[^ ]+ (.+)$/$1/' + + curl -s ftp.kernel.org/pub/linux/kernel/ | \ + perl -lne 'print if s/^d[-rwx]{9}(?: +[^ ]+){7} (.+)$/$1/' + +If you need to parse LIST output, libcurl provides the ability to specify a +wildcard to download multiple files from an FTP directory. + +## I want a different time-out + +Sometimes users realize that `CURLOPT_TIMEOUT` and `CURLOPT_CONNECTIMEOUT` are +not sufficiently advanced or flexible to cover all the various use cases and +scenarios applications end up with. + +libcurl offers many more ways to time-out operations. A common alternative is +to use the `CURLOPT_LOW_SPEED_LIMIT` and `CURLOPT_LOW_SPEED_TIME` options to +specify the lowest possible speed to accept before to consider the transfer +timed out. + +The most flexible way is by writing your own time-out logic and using +`CURLOPT_XFERINFOFUNCTION` (perhaps in combination with other callbacks) and +use that to figure out exactly when the right condition is met when the +transfer should get stopped. + +## Can I write a server with libcurl? + +No. libcurl offers no functions or building blocks to build any kind of +Internet protocol server. libcurl is only a client-side library. For server +libraries, you need to continue your search elsewhere but there exist many +good open source ones out there for most protocols you could want a server +for. There are also really good stand-alone servers that have been tested and +proven for many years. There is no need for you to reinvent them. + +## Does libcurl use threads? + +Put simply: no, libcurl will execute in the same thread you call it in. All +callbacks will be called in the same thread as the one you call libcurl in. + +If you want to avoid your thread to be blocked by the libcurl call, you make +sure you use the non-blocking multi API which will do transfers +asynchronously - still in the same single thread. + +libcurl will potentially internally use threads for name resolving, if it was +built to work like that, but in those cases it will create the child threads +by itself and they will only be used and then killed internally by libcurl and +never exposed to the outside. + +# License + +curl and libcurl are released under an MIT/X derivative license. The license +is liberal and should not impose a problem for your project. This section is +just a brief summary for the cases we get the most questions. + +We are not lawyers and this is not legal advice. You should probably consult +one if you want true and accurate legal insights without our prejudice. Note +especially that this section concerns the libcurl license only; compiling in +features of libcurl that depend on other libraries (e.g. OpenSSL) may affect +the licensing obligations of your application. + +## I have a GPL program, can I use the libcurl library? + +Yes + +Since libcurl may be distributed under the MIT/X derivative license, it can be +used together with GPL in any software. + +## I have a closed-source program, can I use the libcurl library? + +Yes + +libcurl does not put any restrictions on the program that uses the library. + +## I have a BSD licensed program, can I use the libcurl library? + +Yes + +libcurl does not put any restrictions on the program that uses the library. + +## I have a program that uses LGPL libraries, can I use libcurl? + +Yes + +The LGPL license does not clash with other licenses. + +## Can I modify curl/libcurl for my program and keep the changes secret? + +Yes + +The MIT/X derivative license practically allows you to do almost anything with +the sources, on the condition that the copyright texts in the sources are left +intact. + +## Can you please change the curl/libcurl license? + +No. + +We have carefully picked this license after years of development and +discussions and a large amount of people have contributed with source code +knowing that this is the license we use. This license puts the restrictions we +want on curl/libcurl and it does not spread to other programs or libraries +that use it. It should be possible for everyone to use libcurl or curl in +their projects, no matter what license they already have in use. + +## What are my obligations when using libcurl in my commercial apps? + +Next to none. All you need to adhere to is the MIT-style license (stated in +the COPYING file) which basically says you have to include the copyright +notice in *all copies* and that you may not use the copyright holder's name +when promoting your software. + +You do not have to release any of your source code. + +You do not have to reveal or make public any changes to the libcurl source +code. + +You do not have to broadcast to the world that you are using libcurl within +your app. + +All we ask is that you disclose *the copyright notice and this permission +notice* somewhere. Most probably like in the documentation or in the section +where other third party dependencies already are mentioned and acknowledged. + +As can be seen [here](https://curl.se/docs/companies.html) and elsewhere, more +and more companies are discovering the power of libcurl and take advantage of +it even in commercial environments. + +## What license does curl use exactly? + +curl is released under an [MIT derivative +license](https://curl.se/docs/copyright.html). It is similar but not identical +to the MIT license. + +The difference is considered big enough to make SPDX list it under its own +identifier: [curl](https://spdx.org/licenses/curl.html). + +The changes done to the license that make it uniquely curl were tiny and +well-intended, but the reasons for them have been forgotten and we strongly +discourage others from doing the same thing. + +# PHP/CURL + +## What is PHP/CURL? + +The module for PHP that makes it possible for PHP programs to access curl +functions from within PHP. + +In the curl project we call this module PHP/CURL to differentiate it from curl +the command line tool and libcurl the library. The PHP team however does not +refer to it like this (for unknown reasons). They call it plain CURL (often +using all caps) or sometimes ext/curl, but both cause much confusion to users +which in turn gives us a higher question load. + +## Who wrote PHP/CURL? + +PHP/CURL was initially written by Sterling Hughes. + +## Can I perform multiple requests using the same handle? + +Yes. + +After a transfer, you just set new options in the handle and make another +transfer. This will make libcurl reuse the same connection if it can. + +## Does PHP/CURL have dependencies? + +PHP/CURL is a module that comes with the regular PHP package. It depends on +and uses libcurl, so you need to have libcurl installed properly before +PHP/CURL can be used. + +# Development + +## Why does curl use C89? + +As with everything in curl, there is a history and we keep using what we have +used before until someone brings up the subject and argues for and works on +changing it. + +We started out using C89 in the 1990s because that was the only way to write a +truly portable C program and have it run as widely as possible. C89 was for a +long time even necessary to make things work on otherwise considered modern +platforms such as Windows. Today, we do not really know how many users that +still require the use of a C89 compiler. + +We will continue to use C89 for as long as nobody brings up a strong enough +reason for us to change our minds. The core developers of the project do not +feel restricted by this and we are not convinced that going C99 will offer us +enough of a benefit to warrant the risk of cutting off a share of users. + +## Will curl be rewritten? + +In one go: no. Little by little over time? Sure. + +Over the years, new languages and clever operating environments come and go. +Every now and then the urge apparently arises to request that we rewrite curl +in another language. + +Some the most important properties in curl are maintaining the API and ABI for +libcurl and keeping the behavior for the command line tool. As long as we can +do that, everything else is up for discussion. To maintain the ABI, we +probably have to maintain a certain amount of code in C, and to remain rock +stable, we will never risk anything by rewriting a lot of things in one go. +That said, we can certainly offer more and more optional backends written in +other languages, as long as those backends can be plugged in at build-time. +Backends can be written in any language, but should probably provide APIs +usable from C to ease integration and transition. diff --git a/docs/HISTORY.md b/docs/HISTORY.md index 21df56f85fa2..abbb2833a5ed 100644 --- a/docs/HISTORY.md +++ b/docs/HISTORY.md @@ -223,6 +223,9 @@ March: security vulnerability: libcurl TFTP Packet Buffer Overflow September: The major SONAME number for libcurl was bumped to 4 due to the removal of ftp third party transfer support. +October: we started to offer the Mozilla CA cert bundle as a PEM file on the +curl website. + November: Added SCP and SFTP support 2007 @@ -326,6 +329,10 @@ April: added the cyassl backend (later renamed to wolfSSL) August: support for HTTP/2 server push + September: started "everything curl". A separate stand-alone book documenting + curl and related info in perhaps a more tutorial style rather than just a + reference, + December: Public Suffix List 2016 @@ -340,6 +347,8 @@ April: added the cyassl backend (later renamed to wolfSSL) 2017 ---- + May: Fastly starts hosting the curl website + July: OSS-Fuzz started fuzzing libcurl September: Added MultiSSL support @@ -390,6 +399,8 @@ April: added the cyassl backend (later renamed to wolfSSL) 2019 ---- + January: Daniel started working full-time on curl, employed by wolfSSL + March: added experimental alt-svc support August: the first HTTP/3 requests with curl. @@ -404,7 +415,8 @@ April: added the cyassl backend (later renamed to wolfSSL) January: added BearSSL support - March: removed support for PolarSSL, added wolfSSH support + March: removed support for PolarSSL, added wolfSSH support. Created the first + dashboard on the website. April: experimental MQTT support @@ -437,6 +449,8 @@ March: added --json, removed mesalink support The curl.se website serves 16,500 GB/month over 462M requests, the official docker image has been pulled 4,098,015,431 times. +April: added support for msh3 as another HTTP/3 backend + October: initial WebSocket support 2023 @@ -447,7 +461,8 @@ March: remove support for curl_off_t < 8 bytes March 31: we started working on a new command line tool for URL parsing and manipulations: trurl. -May: added support for HTTP/2 over HTTPS proxy. Refuse to resolve .onion. +May: added support for HTTP/2 over HTTPS proxy. Refuse to resolve .onion. The +curl GitHub repository reaches 30,000 stars. August: Dropped support for the NSS library @@ -482,5 +497,27 @@ February 5: first 0RTT for QUIC, ssl session import/export February: experimental HTTPS RR support -February 22: The website served 62.95 TB/month; 12.43 billion requests - The docker image has been pulled 6373501745 times. +February 22: The website served 62.95 TB/month; 12.43 billion requests. The +docker image has been pulled 6373501745 times. + +June: we removed support for BearSSL, Secure Transport and msh3 + +October: Daniel gets awarded a gold medal by the Swedish Royal Academy of +Engineering Sciences for his work on curl. + +We counted curl having been installed on 110 operating systems and 28 CPU +architectures. + +November: + + Public curl releases: 271 + Command line options: 273 + curl_easy_setopt() options: 308 + Public functions in libcurl: 100 + Contributors: 3534 + +We drop support for krb-ftp, Heimdal, wolfSSH and the winbuild build system. + +Add support for Apple SecTrust, native CA certs on Apple systems. + +December 15: the website served 78 TB over the last month. diff --git a/docs/HTTP3.md b/docs/HTTP3.md index 2047d4ad2e77..e18277cb3c87 100644 --- a/docs/HTTP3.md +++ b/docs/HTTP3.md @@ -54,7 +54,7 @@ versions do not work. Build OpenSSL (version 3.5.0 or newer): - % git clone --quiet --depth=1 -b openssl-$OPENSSL_VERSION https://github.com/openssl/openssl + % git clone --depth 1 -b openssl-$OPENSSL_VERSION https://github.com/openssl/openssl % cd openssl % ./config --prefix= --libdir=lib % make @@ -93,8 +93,9 @@ Build curl: ## Build with quictls -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*. +OpenSSL before version 3.5 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 quictls (any `+quic` tagged version works): @@ -139,7 +140,7 @@ Build curl: Build GnuTLS: - % git clone --depth 1 https://gitlab.com/gnutls/gnutls.git + % git clone --depth 1 https://gitlab.com/gnutls/gnutls % cd gnutls % ./bootstrap % ./configure --prefix= @@ -181,7 +182,7 @@ Build curl: Build wolfSSL: - % git clone https://github.com/wolfSSL/wolfssl.git + % git clone https://github.com/wolfSSL/wolfssl % cd wolfssl % autoreconf -fi % ./configure --prefix= --enable-quic --enable-session-ticket --enable-earlydata --enable-psk --enable-harden --enable-altcertchains @@ -316,7 +317,7 @@ See this [list of public HTTP/3 servers](https://bagder.github.io/HTTP3-test/) ### HTTPS eyeballing With option `--http3` curl attempts earlier HTTP versions as well should the -connect attempt via HTTP/3 not succeed "fast enough". This strategy is similar +connect attempt via HTTP/3 fail "fast enough". This strategy is similar to IPv4/6 happy eyeballing where the alternate address family is used in parallel after a short delay. @@ -385,7 +386,7 @@ above. Get, build and install nghttp2: - % git clone https://github.com/nghttp2/nghttp2.git + % git clone https://github.com/nghttp2/nghttp2 % cd nghttp2 % autoreconf -fi % PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/home/daniel/build-quictls/lib/pkgconfig:/home/daniel/build-nghttp3/lib/pkgconfig:/home/daniel/build-ngtcp2/lib/pkgconfig LDFLAGS=-L/home/daniel/build-quictls/lib CFLAGS=-I/home/daniel/build-quictls/include ./configure --enable-maintainer-mode --prefix=/home/daniel/build-nghttp2 --disable-shared --enable-app --enable-http3 --without-jemalloc --without-libxml2 --without-systemd diff --git a/docs/INFRASTRUCTURE.md b/docs/INFRASTRUCTURE.md index 13240b31b5fa..6acc8757f010 100644 --- a/docs/INFRASTRUCTURE.md +++ b/docs/INFRASTRUCTURE.md @@ -60,7 +60,7 @@ account. We regularly run our code through the [Coverity static code analyzer](https://scan.coverity.com/) thanks to them offering this service to -us for free. +us free of charge. ## CodeSonar @@ -76,7 +76,7 @@ domain names, including `curl.se` and `curl.dev`. Daniel Stenberg owns these domain names. Until a few years ago, the curl website was present at `curl.haxx.se`. The -`haxx.se` domain is owned by Haxx AB, administrated by Daniel Stenberg. The +`haxx.se` domain is owned by Haxx AB, administered by Daniel Stenberg. The curl.haxx.se name is meant to keep working and be redirecting to curl.se for the foreseeable future. @@ -100,11 +100,11 @@ company). The machine is physically located in Sweden. curl release tarballs are hosted on https://curl.se/download.html. They are uploaded there at release-time by the release manager. -curl-for-win downloads are hosted on https://curl.se/windows and are uploaded +curl-for-win downloads are hosted on https://curl.se/windows/ and are uploaded to the server by Viktor Szakats. -curl-for-QNX downloads are hosted on and are uploaded to -the server by Daniel Stenberg. +curl-for-QNX downloads are hosted on and are uploaded +to the server by Daniel Stenberg. Daily release tarball-like snapshots are generated automatically and are provided for download at . diff --git a/docs/INSTALL-CMAKE.md b/docs/INSTALL-CMAKE.md index e5c6b0d375e6..03b96761459c 100644 --- a/docs/INSTALL-CMAKE.md +++ b/docs/INSTALL-CMAKE.md @@ -221,11 +221,12 @@ target_link_libraries(my_target PRIVATE CURL::libcurl) - `BUILD_EXAMPLES`: Build libcurl examples. Default: `ON` - `BUILD_LIBCURL_DOCS`: Build libcurl man pages. Default: `ON` - `BUILD_MISC_DOCS`: Build misc man pages (e.g. `curl-config` and `mk-ca-bundle`). Default: `ON` -- `BUILD_SHARED_LIBS`: Build shared libraries. Default: `ON` -- `BUILD_STATIC_CURL`: Build curl executable with static libcurl. Default: `OFF` -- `BUILD_STATIC_LIBS`: Build static libraries. Default: `OFF` +- `BUILD_SHARED_LIBS`: Build shared libraries. Default: `ON` (if target platform supports shared libs, otherwise `OFF`) +- `BUILD_STATIC_CURL`: Build curl executable with static libcurl. Default: `OFF` (turns to `ON`, when building static libcurl only) +- `BUILD_STATIC_LIBS`: Build static libraries. Default: `OFF` (turns to `ON` if `BUILD_SHARED_LIBS` is `OFF`) - `BUILD_TESTING`: Build tests. Default: `ON` - `CURL_CLANG_TIDY`: Run the build through `clang-tidy`. Default: `OFF` + If enabled, it implies `CMAKE_UNITY_BUILD=OFF` and `CURL_DISABLE_TYPECHECK=ON`. - `CURL_CLANG_TIDYFLAGS`: Custom options to pass to `clang-tidy`. Default: (empty) - `CURL_CODE_COVERAGE`: Enable code coverage build options. Default: `OFF` - `CURL_COMPLETION_FISH`: Install fish completions. Default: `OFF` @@ -255,10 +256,10 @@ target_link_libraries(my_target PRIVATE CURL::libcurl) ## CA bundle options -- `CURL_CA_BUNDLE`: Path to the CA bundle. Set `none` to disable or `auto` for auto-detection. Default: `auto` -- `CURL_CA_EMBED`: Path to the CA bundle to embed in the curl tool. Default: (disabled) +- `CURL_CA_BUNDLE`: Absolute path to the CA bundle. Set `none` to disable or `auto` for auto-detection. Default: `auto` +- `CURL_CA_EMBED`: Absolute path to the CA bundle to embed in the curl tool. Default: (disabled) - `CURL_CA_FALLBACK`: Use built-in CA store of OpenSSL. Default: `OFF` -- `CURL_CA_PATH`: Location of default CA path. Set `none` to disable or `auto` for auto-detection. Default: `auto` +- `CURL_CA_PATH`: Absolute path to a directory containing CA certificates stored individually. Set `none` to disable or `auto` for auto-detection. Default: `auto` - `CURL_CA_SEARCH_SAFE`: Enable safe CA bundle search (within the curl tool directory) on Windows. Default: `OFF` ## Enabling features @@ -317,10 +318,11 @@ target_link_libraries(my_target PRIVATE CURL::libcurl) - `CURL_DISABLE_SHUFFLE_DNS`: Disable shuffle DNS feature. Default: `OFF` - `CURL_DISABLE_SMB`: Disable SMB. Default: `OFF` - `CURL_DISABLE_SMTP`: Disable SMTP. Default: `OFF` -- `CURL_DISABLE_SOCKETPAIR`: Disable use of socketpair for curl_multi_poll. Default: `OFF` +- `CURL_DISABLE_SOCKETPAIR`: Disable use of socketpair for curl_multi_poll(). Default: `OFF` - `CURL_DISABLE_SRP`: Disable TLS-SRP support. Default: `OFF` - `CURL_DISABLE_TELNET`: Disable Telnet. Default: `OFF` - `CURL_DISABLE_TFTP`: Disable TFTP. Default: `OFF` +- `CURL_DISABLE_TYPECHECK`: Disable curl_easy_setopt()/curl_easy_getinfo() type checking. Default: `OFF` - `CURL_DISABLE_VERBOSE_STRINGS`: Disable verbose strings. Default: `OFF` - `CURL_DISABLE_WEBSOCKETS`: Disable WebSocket. Default: `OFF` - `HTTP_ONLY`: Disable all protocols except HTTP (This overrides all `CURL_DISABLE_*` options). Default: `OFF` @@ -354,6 +356,7 @@ Details via CMake - `CURL_USE_GNUTLS`: Enable GnuTLS for SSL/TLS. Default: `OFF` - `CURL_USE_GSASL`: Use libgsasl. Default: `OFF` - `CURL_USE_GSSAPI`: Use GSSAPI implementation. Default: `OFF` +- `CURL_USE_LIBBACKTRACE`: Use [libbacktrace](https://github.com/ianlancetaylor/libbacktrace). Requires build with TrackMemory and DWARF debug information. Default: `OFF` - `CURL_USE_LIBPSL`: Use libpsl. Default: `ON` - `CURL_USE_LIBSSH2`: Use libssh2. Default: `ON` - `CURL_USE_LIBSSH`: Use libssh. Default: `OFF` @@ -379,14 +382,14 @@ Details via CMake ## Dependency options (via CMake) -- `OPENSSL_ROOT_DIR`: Set this variable to the root installation of OpenSSL (and forks). -- `OPENSSL_INCLUDE_DIR`: The OpenSSL include directory. -- `OPENSSL_SSL_LIBRARY`: Path to `ssl` library. With MSVC, CMake uses variables `SSL_EAY_DEBUG`/`SSL_EAY_RELEASE` instead. -- `OPENSSL_CRYPTO_LIBRARY`: Path to `crypto` library. With MSVC, CMake uses variables `LIB_EAY_DEBUG`/`LIB_EAY_RELEASE` instead. +- `OPENSSL_ROOT_DIR`: Absolute path to the root installation of OpenSSL (and forks). +- `OPENSSL_INCLUDE_DIR`: Absolute path to OpenSSL include directory. +- `OPENSSL_SSL_LIBRARY`: Absolute path to `ssl` library. With MSVC, CMake uses variables `SSL_EAY_DEBUG`/`SSL_EAY_RELEASE` instead. +- `OPENSSL_CRYPTO_LIBRARY`: Absolute path to `crypto` library. With MSVC, CMake uses variables `LIB_EAY_DEBUG`/`LIB_EAY_RELEASE` instead. - `OPENSSL_USE_STATIC_LIBS`: Look for static OpenSSL libraries. -- `ZLIB_INCLUDE_DIR`: The zlib include directory. -- `ZLIB_LIBRARY`: Path to `zlib` library. -- `ZLIB_USE_STATIC_LIBS`: Look for static ZLIB library (requires CMake v3.24). +- `ZLIB_INCLUDE_DIR`: Absolute path to zlib include directory. +- `ZLIB_LIBRARY`: Absolute path to `zlib` library. +- `ZLIB_USE_STATIC_LIBS`: Look for static `zlib` library (requires CMake v3.24). ## Dependency options (tools) @@ -395,62 +398,82 @@ Details via CMake ## Dependency options (libraries) -- `AMISSL_INCLUDE_DIR`: The AmiSSL include directory. -- `AMISSL_STUBS_LIBRARY`: Path to `amisslstubs` library. -- `AMISSL_AUTO_LIBRARY`: Path to `amisslauto` library. -- `BROTLI_INCLUDE_DIR`: The brotli include directory. -- `BROTLICOMMON_LIBRARY`: Path to `brotlicommon` library. -- `BROTLIDEC_LIBRARY`: Path to `brotlidec` library. -- `CARES_INCLUDE_DIR`: The c-ares include directory. -- `CARES_LIBRARY`: Path to `cares` library. -- `DL_LIBRARY`: Path to `dl` library. (for Rustls) -- `GSS_ROOT_DIR`: Set this variable to the root installation of GSS. (also supported as environment) -- `LDAP_LIBRARY`: Name or full path to `ldap` library. Default: `ldap` -- `LDAP_LBER_LIBRARY`: Name or full path to `lber` library. Default: `lber` -- `LDAP_INCLUDE_DIR`: Path to LDAP include directory. -- `LIBGSASL_INCLUDE_DIR`: The libgsasl include directory. -- `LIBGSASL_LIBRARY`: Path to `libgsasl` library. -- `LIBIDN2_INCLUDE_DIR`: The libidn2 include directory. -- `LIBIDN2_LIBRARY`: Path to `libidn2` library. -- `LIBPSL_INCLUDE_DIR`: The libpsl include directory. -- `LIBPSL_LIBRARY`: Path to `libpsl` library. -- `LIBRTMP_INCLUDE_DIR`: The librtmp include directory. -- `LIBRTMP_LIBRARY`: Path to `librtmp` library. -- `LIBSSH_INCLUDE_DIR`: The libssh include directory. -- `LIBSSH_LIBRARY`: Path to `libssh` library. -- `LIBSSH2_INCLUDE_DIR`: The libssh2 include directory. -- `LIBSSH2_LIBRARY`: Path to `libssh2` library. -- `LIBUV_INCLUDE_DIR`: The libuv include directory. -- `LIBUV_LIBRARY`: Path to `libuv` library. -- `MATH_LIBRARY`: Path to `m` library. (for Rustls, wolfSSL) -- `MBEDTLS_INCLUDE_DIR`: The mbedTLS include directory. -- `MBEDTLS_LIBRARY`: Path to `mbedtls` library. -- `MBEDX509_LIBRARY`: Path to `mbedx509` library. -- `MBEDCRYPTO_LIBRARY`: Path to `mbedcrypto` library. -- `NGHTTP2_INCLUDE_DIR`: The nghttp2 include directory. -- `NGHTTP2_LIBRARY`: Path to `nghttp2` library. -- `NGHTTP3_INCLUDE_DIR`: The nghttp3 include directory. -- `NGHTTP3_LIBRARY`: Path to `nghttp3` library. -- `NGTCP2_INCLUDE_DIR`: The ngtcp2 include directory. -- `NGTCP2_LIBRARY`: Path to `ngtcp2` library. -- `NGTCP2_CRYPTO_BORINGSSL_LIBRARY`: Path to `ngtcp2_crypto_boringssl` library. (also for AWS-LC) -- `NGTCP2_CRYPTO_GNUTLS_LIBRARY`: Path to `ngtcp2_crypto_gnutls` library. -- `NGTCP2_CRYPTO_LIBRESSL_LIBRARY`: Path to `ngtcp2_crypto_libressl` library. (requires ngtcp2 1.15.0+) -- `NGTCP2_CRYPTO_OSSL_LIBRARY`: Path to `ngtcp2_crypto_ossl` library. -- `NGTCP2_CRYPTO_QUICTLS_LIBRARY`: Path to `ngtcp2_crypto_quictls` library. (also for LibreSSL with ngtcp2 <1.15.0) -- `NGTCP2_CRYPTO_WOLFSSL_LIBRARY`: Path to `ngtcp2_crypto_wolfssl` library. -- `NETTLE_INCLUDE_DIR`: The nettle include directory. -- `NETTLE_LIBRARY`: Path to `nettle` library. -- `PTHREAD_LIBRARY`: Path to `pthread` library. (for Rustls) -- `QUICHE_INCLUDE_DIR`: The quiche include directory. -- `QUICHE_LIBRARY`: Path to `quiche` library. -- `RUSTLS_INCLUDE_DIR`: The Rustls include directory. -- `RUSTLS_LIBRARY`: Path to `rustls` library. -- `WATT_ROOT`: Set this variable to the root installation of Watt-32. -- `WOLFSSL_INCLUDE_DIR`: The wolfSSL include directory. -- `WOLFSSL_LIBRARY`: Path to `wolfssl` library. -- `ZSTD_INCLUDE_DIR`: The zstd include directory. -- `ZSTD_LIBRARY`: Path to `zstd` library. +- `AMISSL_INCLUDE_DIR`: Absolute path to AmiSSL include directory. +- `AMISSL_STUBS_LIBRARY`: Absolute path to `amisslstubs` library. +- `AMISSL_AUTO_LIBRARY`: Absolute path to `amisslauto` library. +- `BROTLI_INCLUDE_DIR`: Absolute path to brotli include directory. +- `BROTLICOMMON_LIBRARY`: Absolute path to `brotlicommon` library. +- `BROTLIDEC_LIBRARY`: Absolute path to `brotlidec` library. +- `CARES_INCLUDE_DIR`: Absolute path to c-ares include directory. +- `CARES_LIBRARY`: Absolute path to `cares` library. +- `DL_LIBRARY`: Absolute path to `dl` library. (for Rustls) +- `GNUTLS_INCLUDE_DIR`: Absolute path to GnuTLS include directory. +- `GNUTLS_LIBRARY`: Absolute path to `gnutls` library. +- `GSS_ROOT_DIR`: Absolute path to the root installation of GSS. (also supported as environment) +- `LDAP_INCLUDE_DIR`: Absolute path to LDAP include directory. +- `LDAP_LIBRARY`: Absolute path to `ldap` library. +- `LDAP_LBER_LIBRARY`: Absolute path to `lber` library. +- `LIBBACKTRACE_INCLUDE_DIR`: Absolute path to libbacktrace include directory (https://github.com/ianlancetaylor/libbacktrace). +- `LIBBACKTRACE_LIBRARY`: Absolute path to `libbacktrace` library. +- `LIBGSASL_INCLUDE_DIR`: Absolute path to libgsasl include directory. +- `LIBGSASL_LIBRARY`: Absolute path to `libgsasl` library. +- `LIBIDN2_INCLUDE_DIR`: Absolute path to libidn2 include directory. +- `LIBIDN2_LIBRARY`: Absolute path to `libidn2` library. +- `LIBPSL_INCLUDE_DIR`: Absolute path to libpsl include directory. +- `LIBPSL_LIBRARY`: Absolute path to `libpsl` library. +- `LIBRTMP_INCLUDE_DIR`: Absolute path to librtmp include directory. +- `LIBRTMP_LIBRARY`: Absolute path to `librtmp` library. +- `LIBSSH_INCLUDE_DIR`: Absolute path to libssh include directory. +- `LIBSSH_LIBRARY`: Absolute path to `libssh` library. +- `LIBSSH2_INCLUDE_DIR`: Absolute path to libssh2 include directory. +- `LIBSSH2_LIBRARY`: Absolute path to `libssh2` library. +- `LIBUV_INCLUDE_DIR`: Absolute path to libuv include directory. +- `LIBUV_LIBRARY`: Absolute path to `libuv` library. +- `MATH_LIBRARY`: Absolute path to `m` library. (for Rustls, wolfSSL) +- `MBEDTLS_INCLUDE_DIR`: Absolute path to mbedTLS include directory. +- `MBEDTLS_LIBRARY`: Absolute path to `mbedtls` library. +- `MBEDX509_LIBRARY`: Absolute path to `mbedx509` library. +- `MBEDCRYPTO_LIBRARY`: Absolute path to `mbedcrypto` library. +- `NGHTTP2_INCLUDE_DIR`: Absolute path to nghttp2 include directory. +- `NGHTTP2_LIBRARY`: Absolute path to `nghttp2` library. +- `NGHTTP3_INCLUDE_DIR`: Absolute path to nghttp3 include directory. +- `NGHTTP3_LIBRARY`: Absolute path to `nghttp3` library. +- `NGTCP2_INCLUDE_DIR`: Absolute path to ngtcp2 include directory. +- `NGTCP2_LIBRARY`: Absolute path to `ngtcp2` library. +- `NGTCP2_CRYPTO_BORINGSSL_LIBRARY`: Absolute path to `ngtcp2_crypto_boringssl` library. (also for AWS-LC) +- `NGTCP2_CRYPTO_GNUTLS_LIBRARY`: Absolute path to `ngtcp2_crypto_gnutls` library. +- `NGTCP2_CRYPTO_LIBRESSL_LIBRARY`: Absolute path to `ngtcp2_crypto_libressl` library. (requires ngtcp2 1.15.0+) +- `NGTCP2_CRYPTO_OSSL_LIBRARY`: Absolute path to `ngtcp2_crypto_ossl` library. +- `NGTCP2_CRYPTO_QUICTLS_LIBRARY`: Absolute path to `ngtcp2_crypto_quictls` library. (also for LibreSSL with ngtcp2 <1.15.0) +- `NGTCP2_CRYPTO_WOLFSSL_LIBRARY`: Absolute path to `ngtcp2_crypto_wolfssl` library. +- `NETTLE_INCLUDE_DIR`: Absolute path to nettle include directory. +- `NETTLE_LIBRARY`: Absolute path to `nettle` library. +- `PTHREAD_LIBRARY`: Absolute path to `pthread` library. (for Rustls) +- `QUICHE_INCLUDE_DIR`: Absolute path to quiche include directory. +- `QUICHE_LIBRARY`: Absolute path to `quiche` library. +- `RUSTLS_INCLUDE_DIR`: Absolute path to Rustls include directory. +- `RUSTLS_LIBRARY`: Absolute path to `rustls` library. +- `WATT_ROOT`: Absolute path to the root installation of Watt-32. +- `WOLFSSL_INCLUDE_DIR`: Absolute path to wolfSSL include directory. +- `WOLFSSL_LIBRARY`: Absolute path to `wolfssl` library. +- `ZSTD_INCLUDE_DIR`: Absolute path to zstd include directory. +- `ZSTD_LIBRARY`: Absolute path to `zstd` library. + +Examples: + +- `-DLIBPSL_INCLUDE_DIR=/path/to/libpl/include`, + which directory contains `libpsl.h`. + No ending slash or backslash is necessary. + +- `-DNGHTTP3_INCLUDE_DIR=/path/to/libnghttp3/include`, + which directory contains an `nghttp3` subdirectory with `.h` files in it. + +- `-DLIBPSL_LIBRARY=/path/to/libpsl/lib/libpsl.a` + Always a single library, with its complete filename, as-is on the file system. + +- `-DOPENSSL_ROOT_DIR=/path/to/openssl`, + which directory (typically) contains `include` and `lib` subdirectories. + No ending slash or backslash is necessary. ## Test tools @@ -461,6 +484,8 @@ Details via CMake - `DANTED`: Default: `danted` - `TEST_NGHTTPX`: Default: `nghttpx` - `VSFTPD`: Default: `vsftps` +- `SSHD`: Default: `sshd` +- `SFTPD`: Default: `sftp-server` ## Feature detection variables @@ -473,9 +498,11 @@ the parent project, ideally in the "extra" find package redirect file: Available variables: +- `HAVE_DES_ECB_ENCRYPT`: `DES_ecb_encrypt` present in OpenSSL (or fork). - `HAVE_GNUTLS_SRP`: `gnutls_srp_verifier` present in GnuTLS. - `HAVE_LDAP_INIT_FD`: `ldap_init_fd` present in LDAP library. - `HAVE_LDAP_URL_PARSE`: `ldap_url_parse` present in LDAP library. +- `HAVE_MBEDTLS_DES_CRYPT_ECB`: `mbedtls_des_crypt_ecb` present in mbedTLS <4. - `HAVE_OPENSSL_SRP`: `SSL_CTX_set_srp_username` present in OpenSSL (or fork). - `HAVE_QUICHE_CONN_SET_QLOG_FD`: `quiche_conn_set_qlog_fd` present in quiche. - `HAVE_RUSTLS_SUPPORTED_HPKE`: `rustls_supported_hpke` present in Rustls (unused if Rustls is detected via `pkg-config`). @@ -517,6 +544,9 @@ Note: These variables are internal and subject to change. - `curl-completion-zsh`: Build shell completions for zsh (built by default if enabled) - `curl-ca-bundle`: Build the CA bundle via `scripts/mk-ca-bundle.pl` - `curl-ca-firefox`: Build the CA bundle via `scripts/firefox-db2pem.sh` +- `curl-listcats`: Generate help category constants for `src/tool_help.h` from documentation. +- `curl-listhelp`: Generate `src/tool_listhelp.c` from documentation. +- `curl-optiontable`: Generate `lib/easyoptions.c` from documentation. # Migrating from Visual Studio IDE Project Files diff --git a/docs/INSTALL.md b/docs/INSTALL.md index 453071afd57b..751b21e62051 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -18,7 +18,7 @@ libcurl from [source code](https://curl.se/download.html). You can download and install curl and libcurl using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager: - git clone https://github.com/Microsoft/vcpkg.git + git clone https://github.com/Microsoft/vcpkg cd vcpkg ./bootstrap-vcpkg.sh ./vcpkg integrate install @@ -141,7 +141,7 @@ These options are provided to select the TLS backend to use. - GnuTLS: `--with-gnutls`. - mbedTLS: `--with-mbedtls` - OpenSSL: `--with-openssl` (also for BoringSSL, AWS-LC, LibreSSL, and quictls) - - rustls: `--with-rustls` + - Rustls: `--with-rustls` - Schannel: `--with-schannel` - wolfSSL: `--with-wolfssl` @@ -200,7 +200,7 @@ Building for Windows XP is required as a minimum. You can build curl with: -- Microsoft Visual Studio 2008 v9.0 or later (`_MSC_VER >= 1500`) +- Microsoft Visual Studio 2010 v10.0 or later (`_MSC_VER >= 1600`) - MinGW-w64 3.0 or later (`__MINGW64_VERSION_MAJOR >= 3`) ## Building Windows DLLs and C runtime (CRT) linkage issues @@ -244,7 +244,7 @@ Either run setup-x86_64.exe, then search and select packages individually, or tr setup-x86_64.exe -P binutils -P gcc-core -P libpsl-devel -P libtool -P perl -P make If the latter, matching packages should appear in the install rows (*is fickle though*) after selecting -the download site i.e. `https://mirrors.kernel.org`. In either case, follow the GUI prompts +the download site i.e. `https://mirrors.kernel.org/`. In either case, follow the GUI prompts until you reach the "Select Packages" window; then select packages, click next, and finish the `cygwin` package installation. @@ -650,22 +650,22 @@ 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. -## 104 Operating Systems - - AIX, AmigaOS, Android, ArcoOS, Aros, Atari FreeMiNT, BeOS, Blackberry - 10, Blackberry Tablet OS, Cell OS, CheriBSD, Chrome OS, Cisco IOS, - DG/UX, DR DOS, Dragonfly BSD, eCOS, FreeBSD, FreeDOS, FreeRTOS, Fuchsia, - Garmin OS, Genode, Haiku, HardenedBSD, HP-UX, Hurd, IBM I, illumos, - Integrity, iOS, ipadOS, IRIX, Linux, Lua RTOS, Mac OS 9, macOS, Maemo, - Mbed, Meego, Micrium, MINIX, Minoca, Moblin, MorphOS, MPE/iX, MS-DOS, - NCR MP-RAS, NetBSD, Netware, NextStep, Nintendo 3DS Nintendo Switch, - NonStop OS, NuttX, OpenBSD, OpenStep, Orbis OS, OS/2, OS21, Plan 9, - PlayStation Portable, QNX, Qubes OS, ReactOS, Redox, RISC OS, ROS, - RTEMS, Sailfish OS, SCO Unix, Serenity, SINIX-Z, SkyOS, software, - Solaris, Sortix, SunOS, Syllable OS, Symbian, Tizen, TPF, Tru64, tvOS, - ucLinux, Ultrix, UNICOS, UnixWare, VMS, vxWorks, watchOS, Wear OS, - WebOS, Wii system Wii U, Windows CE, Windows, Xbox System, Xenix, z/OS, - z/TPF, z/VM, z/VSE, Zephyr +## 108 Operating Systems + + AIX, AmigaOS, Android, ArcaOS, Aros, Atari FreeMiNT, Azure Sphere, BeOS, + Blackberry 10, Blackberry Tablet OS, Cell OS, Cesium, CheriBSD, Chrome OS, + Cisco IOS, DG/UX, DR DOS, Dragonfly BSD, eCOS, FreeBSD, FreeDOS, FreeRTOS, + Fuchsia, Garmin OS, Genode, Haiku, HardenedBSD, HP-UX, Hurd, IBM I, + illumos, Integrity, iOS, ipadOS, IRIX, KasperskyOS, Linux, Lua RTOS, + Mac OS 9, macOS, Maemo, Mbed, Meego, Micrium, MINIX, Minoca, Moblin, + MorphOS, MPE/iX, MS-DOS, NCR MP-RAS, NetBSD, Netware, NextStep, + Nintendo 3DS, Nintendo Switch, NonStop OS, NuttX, OpenBSD, OpenStep, + Orbis OS, OS/2, OS21, PikeOS, Plan 9, PlayStation Portable, QNX, Qubes OS, + ReactOS, Redox, RISC OS, ROS, RTEMS, Sailfish OS, SCO Unix, Serenity, + SINIX-Z, SkyOS, SmartOS, Solaris, Sortix, SunOS, Syllable OS, Symbian, + Tizen, TPF, Tru64, tvOS, ucLinux, Ultrix, UNICOS, UnixWare, visionOS, VMS, + vxWorks, watchOS, Wear OS, WebOS, Wii System Software, Wii U, Windows, + Xbox System, Xenix, z/OS, z/TPF, z/VM, z/VSE, Zephyr ## 28 CPU Architectures diff --git a/docs/INTERNALS.md b/docs/INTERNALS.md index b6b00e924a73..222d9ab5ed69 100644 --- a/docs/INTERNALS.md +++ b/docs/INTERNALS.md @@ -24,19 +24,22 @@ versions of libs and build tools. We aim to support these or later versions. - - OpenSSL 1.0.2a - - LibreSSL 2.9.1 - - GnuTLS 3.1.10 - - mbedTLS 3.2.0 - - zlib 1.2.5.2 - - libssh2 1.9.0 - - c-ares 1.6.0 - - libssh 0.9.0 - - libidn2 2.0.0 - - wolfSSL 3.4.6 - - OpenLDAP 2.0 - - MIT Kerberos 1.3 - - nghttp2 1.15.0 + - brotli 1.0.0 (2017-09-21) + - c-ares 1.6.0 (2008-12-09) + - GnuTLS 3.6.5 (2018-12-01) + - libidn2 2.0.0 (2017-03-29) + - LibreSSL 2.9.1 (2019-04-22) + - libssh 0.9.0 (2019-06-28) + - libssh2 1.9.0 (2019-06-20) + - mbedTLS 3.2.0 (2022-07-11) + - MIT Kerberos 1.3 (2003-07-31) + - nghttp2 1.15.0 (2016-09-25) + - OpenLDAP 2.0 (2000-08-01) + - OpenSSL 3.0.0 (2021-09-07) + - Windows XP 5.1 (2001-08-24 - 2009-04-14) + - wolfSSL 3.4.6 (2017-09-22) + - zlib 1.2.5.2 (2011-12-11) + - zstd 1.0 (2016-08-31) ## Build tools @@ -44,13 +47,14 @@ versions of libs and build tools. we use a few "build tools" and we make sure that we remain functional with these versions: - - GNU Libtool 1.4.2 - - GNU Autoconf 2.59 - - GNU Automake 1.7 - - GNU M4 1.4 - - perl 5.8 - - roffit 0.5 - - cmake 3.7 + - cmake 3.7 (2016-11-11) + - GNU autoconf 2.59 (2003-11-06) + - GNU automake 1.7 (2002-09-25) + - GNU libtool 1.4.2 (2001-09-11) + - GNU m4 1.4 (2007-09-21) + - mingw-w64 3.0 (2013-09-20) + - perl 5.8 (2002-07-19), on Windows: 5.22 (2015-06-01) + - Visual Studio 2010 10.0 (2010-04-12 - 2020-07-14) Library Symbols =============== diff --git a/docs/IPFS.md b/docs/IPFS.md index 82dae9439990..c39f802dd918 100644 --- a/docs/IPFS.md +++ b/docs/IPFS.md @@ -7,22 +7,38 @@ SPDX-License-Identifier: curl # IPFS For an overview about IPFS, visit the [IPFS project site](https://ipfs.tech/). -In IPFS there are two protocols. IPFS and IPNS (their workings are explained in detail [here](https://docs.ipfs.tech/concepts/)). The ideal way to access data on the IPFS network is through those protocols. For example to access the Big Buck Bunny video the ideal way to access it is like: `ipfs://bafybeigagd5nmnn2iys2f3doro7ydrevyr2mzarwidgadawmamiteydbzi` +In IPFS there are two protocols. IPFS and IPNS (their workings are explained +in detail [here](https://docs.ipfs.tech/concepts/)). The ideal way to access +data on the IPFS network is through those protocols. For example to access +the Big Buck Bunny video the ideal way to access it is like: +`ipfs://bafybeigagd5nmnn2iys2f3doro7ydrevyr2mzarwidgadawmamiteydbzi` ## IPFS Gateways IPFS Gateway acts as a bridge between traditional HTTP clients and IPFS. -IPFS Gateway specifications of HTTP semantics can be found [here](https://specs.ipfs.tech/http-gateways/). +IPFS Gateway specifications of HTTP semantics can be found +[here](https://specs.ipfs.tech/http-gateways/). ### Deserialized responses -By default, a gateway acts as a bridge between traditional HTTP clients and IPFS and performs necessary hash verification and deserialization. Through such gateway, users can download files, directories, and other content-addressed data stored with IPFS or IPNS as if they were stored in a traditional web server. +By default, a gateway acts as a bridge between traditional HTTP clients and +IPFS and performs necessary hash verification and deserialization. Through such +gateway, users can download files, directories, and other content-addressed +data stored with IPFS or IPNS as if they were stored in a traditional web +server. ### Verifiable responses -By explicitly requesting [application/vnd.ipld.raw](https://www.iana.org/assignments/media-types/application/vnd.ipld.raw) or [application/vnd.ipld.car](https://www.iana.org/assignments/media-types/application/vnd.ipld.car) responses, by means defined in [Trustless Gateway Specification](https://specs.ipfs.tech/http-gateways/trustless-gateway/), the user is able to fetch raw content-addressed data and [perform hash verification themselves](https://docs.ipfs.tech/reference/http/gateway/#trustless-verifiable-retrieval). +By explicitly requesting +[application/vnd.ipld.raw](https://www.iana.org/assignments/media-types/application/vnd.ipld.raw) or +[application/vnd.ipld.car](https://www.iana.org/assignments/media-types/application/vnd.ipld.car) +responses, by means defined in +[Trustless Gateway Specification](https://specs.ipfs.tech/http-gateways/trustless-gateway/), +the user is able to fetch raw content-addressed data and +[perform hash verification themselves](https://docs.ipfs.tech/reference/http/gateway/#trustless-verifiable-retrieval). -This enables users to use untrusted, public gateways without worrying they might return invalid/malicious bytes. +This enables users to use untrusted, public gateways without worrying they +might return invalid/malicious bytes. ## IPFS and IPNS protocol handling @@ -43,9 +59,9 @@ in this link: `http://127.0.0.1:8080/ipfs/bafybeigagd5nmnn2iys2f3doro7ydrevyr2mzarwidgadawmamiteydbzi` -## cURL handling of the IPFS protocols +## curl handling of the IPFS protocols -The IPFS integration in cURL hides this gateway logic for you. Instead of +The IPFS integration in curl hides this gateway logic for you. Instead of providing a full URL to a file on IPFS like this: ``` @@ -57,7 +73,7 @@ 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 +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 @@ -67,7 +83,7 @@ gateway. ### Automatic gateway detection -When you provide no additional details to cURL then it: +When you provide no additional details to curl then it: 1. First looks for the `IPFS_GATEWAY` environment variable and use that if it is set. @@ -75,12 +91,12 @@ When you provide no additional details to cURL then it: means that you have a local gateway running and that file contains the URL to your local gateway. -If cURL fails, you are presented with an error message and a link to this page +If curl fails, you are 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 +You can also provide a `--ipfs-gateway` argument to curl. This overrules any other gateway setting. curl does not fallback to the other options if the provided gateway did not work. @@ -107,21 +123,21 @@ option follows the redirect. ## Error messages and hints -Depending on the arguments, cURL could present the user with an error. +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 could not find it. 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 +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 its URL in `~/.ipfs/gateway`. If you are already running a gateway, make sure it exposes -the file where cURL expects to find it. +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. +the `--ipfs-gateway` flag to the curl command. ### Malformed gateway URL diff --git a/docs/KNOWN_BUGS b/docs/KNOWN_BUGS deleted file mode 100644 index d4e4423094ef..000000000000 --- a/docs/KNOWN_BUGS +++ /dev/null @@ -1,652 +0,0 @@ - _ _ ____ _ - ___| | | | _ \| | - / __| | | | |_) | | - | (__| |_| | _ <| |___ - \___|\___/|_| \_\_____| - - Known Bugs - -These are problems and bugs known to exist at the time of this release. Feel -free to join in and help us correct one or more of these. Also be sure to -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 - - 2. TLS - 2.1 IMAPS connection fails with Rustls error - 2.2 Access violation sending client cert with Schannel - 2.5 Client cert handling with Issuer DN differs between backends - 2.7 Client cert (MTLS) issues with Schannel - 2.11 Schannel TLS 1.2 handshake bug in old Windows versions - 2.13 CURLOPT_CERTINFO results in CURLE_OUT_OF_MEMORY with Schannel - 2.14 mbedTLS and CURLE_AGAIN handling - - 3. Email protocols - 3.1 IMAP SEARCH ALL truncated response - 3.2 No disconnect command - 3.4 AUTH PLAIN for SMTP is not working on all servers - 3.5 APOP authentication fails on POP3 - 3.6 POP3 issue when reading small chunks - - 4. Command line - 4.1 -T /dev/stdin may upload with an incorrect content length - 4.2 -T - always uploads chunked - - 5. Build and portability issues - 5.1 OS400 port requires deprecated IBM library - 5.2 curl-config --libs contains private details - 5.3 LDFLAGS passed too late making libs linked incorrectly - 5.6 Cygwin: make install installs curl-config.1 twice - 5.12 flaky CI builds - 5.13 long paths are not fully supported on Windows - 5.15 Unicode on Windows - - 6. Authentication - 6.1 Digest auth-int for PUT/POST - 6.2 MIT Kerberos for Windows build - 6.3 NTLM in system context uses wrong name - 6.5 NTLM does not support password with Unicode 'SECTION SIGN' character - 6.6 libcurl can fail to try alternatives with --proxy-any - 6.7 Do not clear digest for single realm - 6.9 SHA-256 digest not supported in Windows SSPI builds - 6.10 curl never completes Negotiate over HTTP - 6.11 Negotiate on Windows fails - 6.13 Negotiate against Hadoop HDFS - - 7. FTP - 7.4 FTP with ACCT - 7.12 FTPS directory listing hangs on Windows with Schannel - - 9. SFTP and SCP - 9.1 SFTP does not do CURLOPT_POSTQUOTE correct - 9.3 Remote recursive folder creation with SFTP - 9.4 libssh blocking and infinite loop problem - 9.5 Cygwin: "WARNING: UNPROTECTED PRIVATE KEY FILE!" - - 10. Connection - 10.1 --interface with link-scoped IPv6 address - 10.2 Does not acknowledge getaddrinfo sorting policy - - 11. Internals - 11.1 gssapi library name + version is missing in curl_version_info() - 11.2 error buffer not set if connection to multiple addresses fails - 11.4 HTTP test server 'connection-monitor' problems - 11.5 Connection information when using TCP Fast Open - 11.6 test cases sometimes timeout - 11.7 CURLOPT_CONNECT_TO does not work for HTTPS proxy - 11.8 WinIDN test failures - 11.9 setting a disabled option should return CURLE_NOT_BUILT_IN - - 12. LDAP - 12.1 OpenLDAP hangs after returning results - 12.2 LDAP on Windows does authentication wrong? - 12.3 LDAP on Windows does not work - 12.4 LDAPS requests to ActiveDirectory server hang - - 13. TCP/IP - 13.1 telnet code does not handle partial writes properly - 13.2 Trying local ports fails on Windows - - 15. CMake - 15.1 cmake outputs: no version information available - 15.6 uses -lpthread instead of Threads::Threads - 15.7 generated .pc file contains strange entries - 15.13 CMake build with MIT Kerberos does not work - - 16. aws-sigv4 - 16.2 aws-sigv4 does not handle multipart/form-data correctly - - 17. HTTP/2 - 17.1 HTTP/2 prior knowledge over proxy - 17.2 HTTP/2 frames while in the connection pool kill reuse - 17.3 ENHANCE_YOUR_CALM causes infinite retries - 17.4 HTTP/2 + TLS spends a lot of time in recv - - 18. HTTP/3 - 18.1 connection migration does not work - 18.2 quiche: QUIC connection is draining - 18.3 OpenSSL-QUIC problems on google.com - - 19. RTSP - 19.1 Some methods do not support response bodies - -============================================================================== - -1. HTTP - -2. TLS - -2.1 IMAPS connection fails with Rustls error - - https://github.com/curl/curl/issues/10457 - -2.2 Access violation sending client cert with Schannel - - When using Schannel to do client certs, curl sets PKCS12_NO_PERSIST_KEY to - avoid leaking the private key into the filesystem. Unfortunately that flag - instead seems to trigger a crash. - - See https://github.com/curl/curl/issues/17626 - -2.5 Client cert handling with Issuer DN differs between backends - - When the specified client certificate does not match any of the - server-specified DNs, the OpenSSL and GnuTLS backends behave differently. - The github discussion may contain a solution. - - See https://github.com/curl/curl/issues/1411 - -2.7 Client cert (MTLS) issues with Schannel - - See https://github.com/curl/curl/issues/3145 - -2.11 Schannel TLS 1.2 handshake bug in old Windows versions - - In old versions of Windows such as 7 and 8.1 the Schannel TLS 1.2 handshake - implementation likely has a bug that can rarely cause the key exchange to - fail, resulting in error SEC_E_BUFFER_TOO_SMALL or SEC_E_MESSAGE_ALTERED. - - https://github.com/curl/curl/issues/5488 - -2.13 CURLOPT_CERTINFO results in CURLE_OUT_OF_MEMORY with Schannel - - https://github.com/curl/curl/issues/8741 - -2.14 mbedTLS and CURLE_AGAIN handling - - https://github.com/curl/curl/issues/15801 - -3. Email protocols - -3.1 IMAP SEARCH ALL truncated response - - IMAP "SEARCH ALL" truncates output on large boxes. "A quick search of the - code reveals that pingpong.c contains some truncation code, at line 408, when - it deems the server response to be too large truncating it to 40 characters" - https://curl.se/bug/view.cgi?id=1366 - -3.2 No disconnect command - - The disconnect commands (LOGOUT and QUIT) may not be sent by IMAP, POP3 and - SMTP if a failure occurs during the authentication phase of a connection. - -3.4 AUTH PLAIN for SMTP is not working on all servers - - Specifying "--login-options AUTH=PLAIN" on the command line does not seem to - work correctly. - - See https://github.com/curl/curl/issues/4080 - -3.5 APOP authentication fails on POP3 - - See https://github.com/curl/curl/issues/10073 - -3.6 POP3 issue when reading small chunks - - CURL_DBG_SOCK_RMAX=4 ./runtests.pl -v 982 - - See https://github.com/curl/curl/issues/12063 - -4. Command line - -4.1 -T /dev/stdin may upload with an incorrect content length - - -T stats the path to figure out its size in bytes to use it as Content-Length - if it is a regular file. - - The problem with that is that, on BSDs and some other UNIXes (not Linux), - open(path) may not give you a file descriptor with a 0 offset from the start - of the file. - - See https://github.com/curl/curl/issues/12177 - -4.2 -T - always uploads chunked - - When the `<` shell operator is used. curl should realise that stdin is a - regular file in this case, and that it can do a non-chunked upload, like it - would do if you used -T file. - - See https://github.com/curl/curl/issues/12171 - -5. Build and portability issues - -5.1 OS400 port requires deprecated IBM library - - curl for OS400 requires QADRT to build, which provides ASCII wrappers for - libc/POSIX functions in the ILE, but IBM no longer supports or even offers - this library to download. - - See https://github.com/curl/curl/issues/5176 - -5.2 curl-config --libs contains private details - - "curl-config --libs" include details set in LDFLAGS when configure is run - that might be needed only for building libcurl. Further, curl-config --cflags - suffers from the same effects with CFLAGS/CPPFLAGS. - -5.3 LDFLAGS passed too late making libs linked incorrectly - - Compiling latest curl on HP-UX and linking against a custom OpenSSL (which is - on the default loader/linker path), fails because the generated Makefile has - LDFLAGS passed on after LIBS. - - See https://github.com/curl/curl/issues/14893 - -5.6 Cygwin: make install installs curl-config.1 twice - - https://github.com/curl/curl/issues/8839 - -5.12 flaky CI builds - - We run many CI builds for each commit and PR on github, and especially a - number of the Windows builds are flaky. This means that we rarely get all CI - builds go green and complete without errors. This is unfortunate as it makes - us sometimes miss actual build problems and it is surprising to newcomers to - the project who (rightfully) do not expect this. - - See https://github.com/curl/curl/issues/6972 - -5.13 long paths are not fully supported on Windows - - curl on Windows cannot access long paths (paths longer than 260 characters). - However, as a workaround, the Windows path prefix \\?\ which disables all - path interpretation may work to allow curl to access the path. For example: - \\?\c:\longpath. - - See https://github.com/curl/curl/issues/8361 - -5.15 Unicode on Windows - - Passing in a Unicode filename with -o: - - https://github.com/curl/curl/issues/11461 - - Passing in Unicode character with -d: - - https://github.com/curl/curl/issues/12231 - - Windows Unicode builds use homedir in current locale - - The Windows Unicode builds of curl use the current locale, but expect Unicode - UTF-8 encoded paths for internal use such as open, access and stat. The - user's home directory is retrieved via curl_getenv in the current locale and - not as UTF-8 encoded Unicode. - - See https://github.com/curl/curl/pull/7252 and - https://github.com/curl/curl/pull/7281 - - Cannot handle Unicode arguments in non-Unicode builds on Windows - - If a URL or filename cannot be encoded using the user's current codepage then - it can only be encoded properly in the Unicode character set. Windows uses - UTF-16 encoding for Unicode and stores it in wide characters, however curl - and libcurl are not equipped for that at the moment except when built with - _UNICODE and UNICODE defined. Except for Cygwin, Windows cannot use UTF-8 as - a locale. - - https://curl.se/bug/?i=345 - https://curl.se/bug/?i=731 - https://curl.se/bug/?i=3747 - - NTLM authentication and Unicode - - NTLM authentication involving Unicode username or password only works - properly if built with UNICODE defined together with the Schannel backend. - The original problem was mentioned in: - https://curl.se/mail/lib-2009-10/0024.html - https://curl.se/bug/view.cgi?id=896 - - The Schannel version verified to work as mentioned in - https://curl.se/mail/lib-2012-07/0073.html - -6. Authentication - -6.1 Digest auth-int for PUT/POST - - We do not support auth-int for Digest using PUT or POST - -6.2 MIT Kerberos for Windows build - - libcurl fails to build with MIT Kerberos for Windows (KfW) due to KfW's - library header files exporting symbols/macros that should be kept private to - the KfW library. See ticket #5601 at https://krbdev.mit.edu/rt/ - -6.3 NTLM in system context uses wrong name - - NTLM authentication using SSPI (on Windows) when (lib)curl is running in - "system context" makes it use wrong(?) username - at least when compared to - what winhttp does. See https://curl.se/bug/view.cgi?id=535 - -6.5 NTLM does not support password with Unicode 'SECTION SIGN' character - - https://en.wikipedia.org/wiki/Section_sign - https://codepoints.net/U+00A7 SECTION SIGN - https://github.com/curl/curl/issues/2120 - -6.6 libcurl can fail to try alternatives with --proxy-any - - When connecting via a proxy using --proxy-any, a failure to establish an - authentication causes libcurl to abort trying other options if the failed - method has a higher preference than the alternatives. As an example, - --proxy-any against a proxy which advertise Negotiate and NTLM, but which - fails to set up Kerberos authentication does not proceed to try - authentication using NTLM. - - https://github.com/curl/curl/issues/876 - -6.7 Do not clear digest for single realm - - https://github.com/curl/curl/issues/3267 - -6.9 SHA-256 digest not supported in Windows SSPI builds - - Windows builds of curl that have SSPI enabled use the native Windows API calls - to create authentication strings. The call to InitializeSecurityContext fails - with SEC_E_QOP_NOT_SUPPORTED which causes curl to fail with CURLE_AUTH_ERROR. - - Microsoft does not document supported digest algorithms and that SEC_E error - code is not a documented error for InitializeSecurityContext (digest). - - https://github.com/curl/curl/issues/6302 - -6.10 curl never completes Negotiate over HTTP - - Apparently it is not working correctly...? - - See https://github.com/curl/curl/issues/5235 - -6.11 Negotiate on Windows fails - - When using --negotiate (or NTLM) with curl on Windows, SSL/TLS handshake - fails despite having a valid kerberos ticket cached. Works without any issue - in Unix/Linux. - - https://github.com/curl/curl/issues/5881 - -6.13 Negotiate authentication against Hadoop HDFS - - https://github.com/curl/curl/issues/8264 - -7. FTP - -7.4 FTP with ACCT - - When doing an operation over FTP that requires the ACCT command (but not when - logging in), the operation fails since libcurl does not detect this and thus - fails to issue the correct command: https://curl.se/bug/view.cgi?id=635 - -7.12 FTPS server compatibility on Windows with Schannel - - FTPS is not widely used with the Schannel TLS backend and so there may be - more bugs compared to other TLS backends such as OpenSSL. In the past users - have reported hanging and failed connections. It is likely some changes to - curl since then fixed the issues. None of the reported issues can be - reproduced any longer. - - If you encounter an issue connecting to your server via FTPS with the latest - curl and Schannel then please search for open issues or file a new issue. - -9. SFTP and SCP - -9.1 SFTP does not do CURLOPT_POSTQUOTE correct - - When libcurl sends CURLOPT_POSTQUOTE commands when connected to an SFTP - server using the multi interface, the commands are not being sent correctly - and instead the connection is "cancelled" (the operation is considered done) - prematurely. There is a half-baked (busy-looping) patch provided in the bug - report but it cannot be accepted as-is. See - https://curl.se/bug/view.cgi?id=748 - -9.3 Remote recursive folder creation with SFTP - - On this servers, the curl fails to create directories on the remote server - even when the CURLOPT_FTP_CREATE_MISSING_DIRS option is set. - - See https://github.com/curl/curl/issues/5204 - -9.4 libssh blocking and infinite loop problem - - In the SSH_SFTP_INIT state for libssh, the ssh session working mode is set to - blocking mode. If the network is suddenly disconnected during sftp - transmission, curl is stuck, even if curl is configured with a timeout. - - https://github.com/curl/curl/issues/8632 - -9.5 Cygwin: "WARNING: UNPROTECTED PRIVATE KEY FILE!" - - Running SCP and SFTP tests on Cygwin makes this warning message appear. - - https://github.com/curl/curl/issues/11244 - -10. Connection - -10.1 --interface with link-scoped IPv6 address - - When you give the `--interface` option telling curl to use a specific - interface for its outgoing traffic in combination with an IPv6 address in the - URL that uses a link-local scope, curl might pick the wrong address from the - named interface and the subsequent transfer fails. - - Example command line: - - curl --interface eth0 'http://[fe80:928d:xxff:fexx:xxxx]/' - - The fact that the given IP address is link-scoped should probably be used as - input to somehow make curl make a better choice for this. - - https://github.com/curl/curl/issues/14782 - -10.2 Does not acknowledge getaddrinfo sorting policy - - Even if a user edits /etc/gai.conf to prefer IPv4, curl still prefers and - tries IPv6 addresses first. - - https://github.com/curl/curl/issues/16718 - -11. Internals - -11.1 gssapi library name + version is missing in curl_version_info() - - The struct needs to be expanded and code added to store this info. - - See https://github.com/curl/curl/issues/13492 - -11.2 error buffer not set if connection to multiple addresses fails - - If you ask libcurl to resolve a hostname like example.com to IPv6 addresses - when you only have IPv4 connectivity. libcurl fails with - CURLE_COULDNT_CONNECT, but the error buffer set by CURLOPT_ERRORBUFFER - remains empty. Issue: https://github.com/curl/curl/issues/544 - -11.4 HTTP test server 'connection-monitor' problems - - The 'connection-monitor' feature of the sws HTTP test server does not work - properly if some tests are run in unexpected order. Like 1509 and then 1525. - - See https://github.com/curl/curl/issues/868 - -11.5 Connection information when using TCP Fast Open - - CURLINFO_LOCAL_PORT (and possibly a few other) fails when TCP Fast Open is - enabled. - - See https://github.com/curl/curl/issues/1332 and - https://github.com/curl/curl/issues/4296 - -11.6 test cases sometimes timeout - - Occasionally, one of the tests timeouts. Inexplicably. - - See https://github.com/curl/curl/issues/13350 - -11.7 CURLOPT_CONNECT_TO does not work for HTTPS proxy - - It is unclear if the same option should even cover the proxy connection or if - if requires a separate option. - - See https://github.com/curl/curl/issues/14481 - -11.8 WinIDN test failures - - Test 165 disabled when built with WinIDN. - -11.9 setting a disabled option should return CURLE_NOT_BUILT_IN - - When curl has been built with specific features or protocols disabled, - setting such options with curl_easy_setopt() should rather return - CURLE_NOT_BUILT_IN instead of CURLE_UNKNOWN_OPTION to signal the difference - to the application - - See https://github.com/curl/curl/issues/15472 - -12. LDAP - -12.1 OpenLDAP hangs after returning results - - By configuration defaults, OpenLDAP automatically chase referrals on - secondary socket descriptors. The OpenLDAP backend is asynchronous and thus - should monitor all socket descriptors involved. Currently, these secondary - descriptors are not monitored, causing OpenLDAP library to never receive - data from them. - - As a temporary workaround, disable referrals chasing by configuration. - - The fix is not easy: proper automatic referrals chasing requires a - synchronous bind callback and monitoring an arbitrary number of socket - descriptors for a single easy handle (currently limited to 5). - - Generic LDAP is synchronous: OK. - - See https://github.com/curl/curl/issues/622 and - https://curl.se/mail/lib-2016-01/0101.html - -12.2 LDAP on Windows does authentication wrong? - - https://github.com/curl/curl/issues/3116 - -12.3 LDAP on Windows does not work - - A simple curl command line getting "ldap://ldap.forumsys.com" returns an - error that says "no memory" ! - - https://github.com/curl/curl/issues/4261 - -12.4 LDAPS requests to ActiveDirectory server hang - - https://github.com/curl/curl/issues/9580 - -13. TCP/IP - -13.1 telnet code does not handle partial writes properly - - It probably does not happen too easily because of how slow and infrequent - sends are normally performed. - -13.2 Trying local ports fails on Windows - - This makes '--local-port [range]' to not work since curl cannot properly - detect if a port is already in use, so it tries the first port, uses that and - then subsequently fails anyway if that was actually in use. - - https://github.com/curl/curl/issues/8112 - -15. CMake - -15.1 cmake outputs: no version information available - - Something in the SONAME generation seems to be wrong in the cmake build. - - https://github.com/curl/curl/issues/11158 - -15.6 uses -lpthread instead of Threads::Threads - - See https://github.com/curl/curl/issues/6166 - -15.7 generated .pc file contains strange entries - - The Libs.private field of the generated .pc file contains -lgcc -lgcc_s -lc - -lgcc -lgcc_s - - See https://github.com/curl/curl/issues/6167 - -15.13 CMake build with MIT Kerberos does not work - - Minimum CMake version was bumped in curl 7.71.0 (#5358) Since CMake 3.2 - try_compile started respecting the CMAKE_EXE_FLAGS. The code dealing with - MIT Kerberos detection sets few variables to potentially weird mix of space, - and ;-separated flags. It had to blow up at some point. All the CMake checks - that involve compilation are doomed from that point, the configured tree - cannot be built. - - https://github.com/curl/curl/issues/6904 - -16. aws-sigv4 - -16.2 aws-sigv4 does not handle multipart/form-data correctly - - https://github.com/curl/curl/issues/13351 - -17. HTTP/2 - -17.1 HTTP/2 prior knowledge over proxy - - https://github.com/curl/curl/issues/12641 - -17.2 HTTP/2 frames while in the connection pool kill reuse - - If the server sends HTTP/2 frames (like for example an HTTP/2 PING frame) to - curl while the connection is held in curl's connection pool, the socket is - found readable when considered for reuse and that makes curl think it is dead - and then it is closed and a new connection gets created instead. - - This is *best* fixed by adding monitoring to connections while they are kept - in the pool so that pings can be responded to appropriately. - -17.3 ENHANCE_YOUR_CALM causes infinite retries - - Infinite retries with 2 parallel requests on one connection receiving GOAWAY - with ENHANCE_YOUR_CALM error code. - - See https://github.com/curl/curl/issues/5119 - -17.4 HTTP/2 + TLS spends a lot of time in recv - - It has been observed that by making the speed limit less accurate we could - improve this performance. (by reverting - https://github.com/curl/curl/commit/db5c9f4f9e0779b49624752b135281a0717b277b) - Can we find a golden middle ground? - - See https://curl.se/mail/lib-2024-05/0026.html and - https://github.com/curl/curl/issues/13416 - -18. HTTP/3 - -18.1 connection migration does not work - - https://github.com/curl/curl/issues/7695 - -18.2 quiche: QUIC connection is draining - - The transfer ends with error "QUIC connection is draining". - - https://github.com/curl/curl/issues/12037 - -18.3 OpenSSL-QUIC problems on google.com - - With some specific Google servers, and seemingly timing dependent, the - OpenSSL-QUIC backend seems to not actually send off the HTTP/3 request which - makes the QUIC connection just sit idle until killed by the server. curl or - OpenSSL bug? - - https://github.com/curl/curl/issues/18336 - -19. RTSP - -19.1 Some methods do not support response bodies - - The RTSP implementation is written to assume that a number of RTSP methods - 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/KNOWN_BUGS.md b/docs/KNOWN_BUGS.md new file mode 100644 index 000000000000..83a30fd9e897 --- /dev/null +++ b/docs/KNOWN_BUGS.md @@ -0,0 +1,548 @@ + + +# Known bugs intro + +These are problems and bugs known to exist at the time of this release. Feel +free to join in and help us correct one or more of these. Also be sure to +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. + +# TLS + +## IMAPS connection fails with Rustls error + +[curl issue 10457](https://github.com/curl/curl/issues/10457) + +## Access violation sending client cert with Schannel + +When using Schannel to do client certs, curl sets `PKCS12_NO_PERSIST_KEY` to +avoid leaking the private key into the filesystem. Unfortunately that flag +instead seems to trigger a crash. + +See [curl issue 17626](https://github.com/curl/curl/issues/17626) + +## Client cert handling with Issuer `DN` differs between backends + +When the specified client certificate does not match any of the +server-specified `DN` fields, the OpenSSL and GnuTLS backends behave +differently. The GitHub discussion may contain a solution. + +See [curl issue 1411](https://github.com/curl/curl/issues/1411) + +## Client cert (MTLS) issues with Schannel + +See [curl issue 3145](https://github.com/curl/curl/issues/3145) + +## Schannel TLS 1.2 handshake bug in old Windows versions + +In old versions of Windows such as 7 and 8.1 the Schannel TLS 1.2 handshake +implementation likely has a bug that can rarely cause the key exchange to +fail, resulting in error SEC_E_BUFFER_TOO_SMALL or SEC_E_MESSAGE_ALTERED. + +[curl issue 5488](https://github.com/curl/curl/issues/5488) + +## `CURLOPT_CERTINFO` results in `CURLE_OUT_OF_MEMORY` with Schannel + +[curl issue 8741](https://github.com/curl/curl/issues/8741) + +## mbedTLS and CURLE_AGAIN handling + +[curl issue 15801](https://github.com/curl/curl/issues/15801) + +# Email protocols + +## IMAP `SEARCH ALL` truncated response + +IMAP `SEARCH ALL` truncates output on large boxes. "A quick search of the code +reveals that `pingpong.c` contains some truncation code, at line 408, when it +deems the server response to be too large truncating it to 40 characters" + +https://curl.se/bug/view.cgi?id=1366 + +## No disconnect command + +The disconnect commands (`LOGOUT` and `QUIT`) may not be sent by IMAP, POP3 +and SMTP if a failure occurs during the authentication phase of a connection. + +## `AUTH PLAIN` for SMTP is not working on all servers + +Specifying `--login-options AUTH=PLAIN` on the command line does not seem to +work correctly. + +See [curl issue 4080](https://github.com/curl/curl/issues/4080) + +## `APOP` authentication fails on POP3 + +See [curl issue 10073](https://github.com/curl/curl/issues/10073) + +## POP3 issue when reading small chunks + + CURL_DBG_SOCK_RMAX=4 ./runtests.pl -v 982 + +See [curl issue 12063](https://github.com/curl/curl/issues/12063) + +# Command line + +## `-T /dev/stdin` may upload with an incorrect content length + +`-T` stats the path to figure out its size in bytes to use it as +`Content-Length` if it is a regular file. + +The problem with that is that on BSD and some other UNIX systems (not Linux), +open(path) may not give you a file descriptor with a 0 offset from the start +of the file. + +See [curl issue 12177](https://github.com/curl/curl/issues/12177) + +## `-T -` always uploads chunked + +When the `<` shell operator is used. curl should realize that stdin is a +regular file in this case, and that it can do a non-chunked upload, like it +would do if you used `-T` file. + +See [curl issue 12171](https://github.com/curl/curl/issues/12171) + +# Build and portability issues + +## OS400 port requires deprecated IBM library + +curl for OS400 requires `QADRT` to build, which provides ASCII wrappers for +libc/POSIX functions in the ILE, but IBM no longer supports or even offers +this library to download. + +See [curl issue 5176](https://github.com/curl/curl/issues/5176) + +## `curl-config --libs` contains private details + +`curl-config --libs` include details set in `LDFLAGS` when configure is run +that might be needed only for building libcurl. Further, `curl-config +--cflags` suffers from the same effects with `CFLAGS`/`CPPFLAGS`. + +## `LDFLAGS` passed too late making libs linked incorrectly + +Compiling latest curl on HP-UX and linking against a custom OpenSSL (which is +on the default loader/linker path), fails because the generated Makefile has +`LDFLAGS` passed on after `LIBS`. + +See [curl issue 14893](https://github.com/curl/curl/issues/14893) + +## Cygwin: make install installs curl-config.1 twice + +[curl issue 8839](https://github.com/curl/curl/issues/8839) + +## flaky CI builds + +We run many CI builds for each commit and PR on GitHub, and especially a +number of the Windows builds are flaky. This means that we rarely get all CI +builds go green and complete without errors. This is unfortunate as it makes +us sometimes miss actual build problems and it is surprising to newcomers to +the project who (rightfully) do not expect this. + +See [curl issue 6972](https://github.com/curl/curl/issues/6972) + +## long paths are not fully supported on Windows + +curl on Windows cannot access long paths (paths longer than 260 characters). +However, as a workaround, the Windows path prefix `\\?\` which disables all +path interpretation may work to allow curl to access the path. For example: +`\\?\c:\longpath`. + +See [curl issue 8361](https://github.com/curl/curl/issues/8361) + +## Unicode on Windows + +Passing in a Unicode filename with -o: + +[curl issue 11461](https://github.com/curl/curl/issues/11461) + +Passing in Unicode character with -d: + +[curl issue 12231](https://github.com/curl/curl/issues/12231) + +Windows Unicode builds use the home directory in current locale. + +The Windows Unicode builds of curl use the current locale, but expect Unicode +UTF-8 encoded paths for internal use such as open, access and stat. The user's +home directory is retrieved via curl_getenv in the current locale and not as +UTF-8 encoded Unicode. + +See [curl pull request 7252](https://github.com/curl/curl/pull/7252) and [curl pull request 7281](https://github.com/curl/curl/pull/7281) + +Cannot handle Unicode arguments in non-Unicode builds on Windows + +If a URL or filename cannot be encoded using the user's current code page then +it can only be encoded properly in the Unicode character set. Windows uses +UTF-16 encoding for Unicode and stores it in wide characters, however curl and +libcurl are not equipped for that at the moment except when built with +_UNICODE and UNICODE defined. Except for Cygwin, Windows cannot use UTF-8 as a +locale. + + https://curl.se/bug/?i=345 + https://curl.se/bug/?i=731 + https://curl.se/bug/?i=3747 + +NTLM authentication and Unicode + +NTLM authentication involving Unicode username or password only works properly +if built with UNICODE defined together with the Schannel backend. The original +problem was mentioned in: https://curl.se/mail/lib-2009-10/0024.html and +https://curl.se/bug/view.cgi?id=896 + +The Schannel version verified to work as mentioned in +https://curl.se/mail/lib-2012-07/0073.html + +# Authentication + +## Digest `auth-int` for PUT/POST + +We do not support auth-int for Digest using PUT or POST + +## MIT Kerberos for Windows build + +libcurl fails to build with MIT Kerberos for Windows (`KfW`) due to its +library header files exporting symbols/macros that should be kept private to +the library. + +## NTLM in system context uses wrong name + +NTLM authentication using SSPI (on Windows) when (lib)curl is running in +"system context" makes it use wrong(?) username - at least when compared to +what `winhttp` does. See https://curl.se/bug/view.cgi?id=535 + +## NTLM does not support password with Unicode 'SECTION SIGN' character + +Code point: U+00A7 + +https://en.wikipedia.org/wiki/Section_sign +[curl issue 2120](https://github.com/curl/curl/issues/2120) + +## libcurl can fail to try alternatives with `--proxy-any` + +When connecting via a proxy using `--proxy-any`, a failure to establish an +authentication causes libcurl to abort trying other options if the failed +method has a higher preference than the alternatives. As an example, +`--proxy-any` against a proxy which advertise Negotiate and NTLM, but which +fails to set up Kerberos authentication does not proceed to try authentication +using NTLM. + +[curl issue 876](https://github.com/curl/curl/issues/876) + +## Do not clear digest for single realm + +[curl issue 3267](https://github.com/curl/curl/issues/3267) + +## SHA-256 digest not supported in Windows SSPI builds + +Windows builds of curl that have SSPI enabled use the native Windows API calls +to create authentication strings. The call to `InitializeSecurityContext` fails +with `SEC_E_QOP_NOT_SUPPORTED` which causes curl to fail with +`CURLE_AUTH_ERROR`. + +Microsoft does not document supported digest algorithms and that `SEC_E` error +code is not a documented error for `InitializeSecurityContext` (digest). + +[curl issue 6302](https://github.com/curl/curl/issues/6302) + +## curl never completes Negotiate over HTTP + +Apparently it is not working correctly...? + +See [curl issue 5235](https://github.com/curl/curl/issues/5235) + +## Negotiate on Windows fails + +When using `--negotiate` (or NTLM) with curl on Windows, SSL/TLS handshake +fails despite having a valid kerberos ticket cached. Works without any issue +in Unix/Linux. + +[curl issue 5881](https://github.com/curl/curl/issues/5881) + +## Negotiate authentication against Hadoop + +[curl issue 8264](https://github.com/curl/curl/issues/8264) + +# FTP + +## FTP with ACCT + +When doing an operation over FTP that requires the `ACCT` command (but not when +logging in), the operation fails since libcurl does not detect this and thus +fails to issue the correct command: https://curl.se/bug/view.cgi?id=635 + +## FTPS server compatibility on Windows with Schannel + +FTPS is not widely used with the Schannel TLS backend and so there may be more +bugs compared to other TLS backends such as OpenSSL. In the past users have +reported hanging and failed connections. It is likely some changes to curl +since then fixed the issues. None of the reported issues can be reproduced any +longer. + +If you encounter an issue connecting to your server via FTPS with the latest +curl and Schannel then please search for open issues or file a new issue. + +# SFTP and SCP + +## SFTP does not do `CURLOPT_POSTQUOTE` correct + +When libcurl sends `CURLOPT_POSTQUOTE` commands when connected to an SFTP +server using the multi interface, the commands are not being sent correctly +and instead the connection is canceled (the operation is considered done) +prematurely. There is a half-baked (busy-looping) patch provided in the bug +report but it cannot be accepted as-is. See +https://curl.se/bug/view.cgi?id=748 + +## Remote recursive folder creation with SFTP + +On this servers, the curl fails to create directories on the remote server +even when the `CURLOPT_FTP_CREATE_MISSING_DIRS` option is set. + +See [curl issue 5204](https://github.com/curl/curl/issues/5204) + +## libssh blocking and infinite loop problem + +In the `SSH_SFTP_INIT` state for libssh, the ssh session working mode is set +to blocking mode. If the network is suddenly disconnected during sftp +transmission, curl is stuck, even if curl is configured with a timeout. + +[curl issue 8632](https://github.com/curl/curl/issues/8632) + +## Cygwin: "WARNING: UNPROTECTED PRIVATE KEY FILE!" + +Running SCP and SFTP tests on Cygwin makes this warning message appear. + +[curl issue 11244](https://github.com/curl/curl/issues/11244) + +# Connection + +## `--interface` with link-scoped IPv6 address + +When you give the `--interface` option telling curl to use a specific +interface for its outgoing traffic in combination with an IPv6 address in the +URL that uses a link-local scope, curl might pick the wrong address from the +named interface and the subsequent transfer fails. + +Example command line: + + curl --interface eth0 'http://[fe80:928d:xxff:fexx:xxxx]/' + +The fact that the given IP address is link-scoped should probably be used as +input to somehow make curl make a better choice for this. + +[curl issue 14782](https://github.com/curl/curl/issues/14782) + +## Does not acknowledge getaddrinfo sorting policy + +Even if a user edits `/etc/gai.conf` to prefer IPv4, curl still prefers and +tries IPv6 addresses first. + +[curl issue 16718](https://github.com/curl/curl/issues/16718) + +## SOCKS-SSPI discards the security context + +After a successful SSPI/GSS-API exchange, the function queries and logs the +authenticated username and reports the supported data-protection level, but +then immediately deletes the negotiated SSPI security context and frees the +credentials before returning. The negotiated context is not stored on the +connection and is therefore never used to protect later SOCKS5 traffic. + +# Internals + +## GSSAPI library name + version is missing in `curl_version_info()` + +The struct needs to be expanded and code added to store this info. + +See [curl issue 13492](https://github.com/curl/curl/issues/13492) + +## error buffer not set if connection to multiple addresses fails + +If you ask libcurl to resolve a hostname like example.com to IPv6 addresses +when you only have IPv4 connectivity. libcurl fails with +`CURLE_COULDNT_CONNECT`, but the error buffer set by `CURLOPT_ERRORBUFFER` +remains empty. Issue: [curl issue 544](https://github.com/curl/curl/issues/544) + +## HTTP test server 'connection-monitor' problems + +The `connection-monitor` feature of the HTTP test server does not work +properly if some tests are run in unexpected order. Like 1509 and then 1525. + +See [curl issue 868](https://github.com/curl/curl/issues/868) + +## Connection information when using TCP Fast Open + +`CURLINFO_LOCAL_PORT` (and possibly a few other) fails when TCP Fast Open is +enabled. + +See [curl issue 1332](https://github.com/curl/curl/issues/1332) and +[curl issue 4296](https://github.com/curl/curl/issues/4296) + +## test cases sometimes timeout + +Occasionally, one of the tests timeouts. Inexplicably. + +See [curl issue 13350](https://github.com/curl/curl/issues/13350) + +## `CURLOPT_CONNECT_TO` does not work for HTTPS proxy + +It is unclear if the same option should even cover the proxy connection or if +if requires a separate option. + +See [curl issue 14481](https://github.com/curl/curl/issues/14481) + +## WinIDN test failures + +Test 165 disabled when built with WinIDN. + +## setting a disabled option should return `CURLE_NOT_BUILT_IN` + +When curl has been built with specific features or protocols disabled, setting +such options with `curl_easy_setopt()` should rather return +`CURLE_NOT_BUILT_IN` instead of `CURLE_UNKNOWN_OPTION` to signal the +difference to the application + +See [curl issue 15472](https://github.com/curl/curl/issues/15472) + +# LDAP + +## OpenLDAP hangs after returning results + +By configuration defaults, OpenLDAP automatically chase referrals on secondary +socket descriptors. The OpenLDAP backend is asynchronous and thus should +monitor all socket descriptors involved. Currently, these secondary +descriptors are not monitored, causing OpenLDAP library to never receive data +from them. + +As a temporary workaround, disable referrals chasing by configuration. + +The fix is not easy: proper automatic referrals chasing requires a synchronous +bind callback and monitoring an arbitrary number of socket descriptors for a +single easy handle (currently limited to 5). + +Generic LDAP is synchronous: OK. + +See [curl issue 622](https://github.com/curl/curl/issues/622) and +https://curl.se/mail/lib-2016-01/0101.html + +## LDAP on Windows does authentication wrong? + +[curl issue 3116](https://github.com/curl/curl/issues/3116) + +## LDAP on Windows does not work + +A simple curl command line getting `ldap://ldap.forumsys.com` returns an error +that says `no memory` ! + +[curl issue 4261](https://github.com/curl/curl/issues/4261) + +## LDAPS requests to Active Directory server hang + +[curl issue 9580](https://github.com/curl/curl/issues/9580) + +# TCP/IP + +## telnet code does not handle partial writes properly + +It probably does not happen too easily because of how slow and infrequent +sends are normally performed. + +## Trying local ports fails on Windows + +This makes `--local-port [range]` to not work since curl cannot properly +detect if a port is already in use, so it tries the first port, uses that and +then subsequently fails anyway if that was actually in use. + +[curl issue 8112](https://github.com/curl/curl/issues/8112) + +# CMake + +## cmake outputs: no version information available + +Something in the SONAME generation seems to be wrong in the cmake build. + +[curl issue 11158](https://github.com/curl/curl/issues/11158) + +## uses `-lpthread` instead of `Threads::Threads` + +See [curl issue 6166](https://github.com/curl/curl/issues/6166) + +## generated `.pc` file contains strange entries + +The `Libs.private` field of the generated `.pc` file contains `-lgcc -lgcc_s +-lc -lgcc -lgcc_s`. + +See [curl issue 6167](https://github.com/curl/curl/issues/6167) + +## CMake build with MIT Kerberos does not work + +Minimum CMake version was bumped in curl 7.71.0 (#5358) Since CMake 3.2 +try_compile started respecting the `CMAKE_EXE_FLAGS`. The code dealing with +MIT Kerberos detection sets few variables to potentially weird mix of space, +and ;-separated flags. It had to blow up at some point. All the CMake checks +that involve compilation are doomed from that point, the configured tree +cannot be built. + +[curl issue 6904](https://github.com/curl/curl/issues/6904) + +# Authentication + +## `--aws-sigv4` does not handle multipart/form-data correctly + +[curl issue 13351](https://github.com/curl/curl/issues/13351) + +# HTTP/2 + +## HTTP/2 prior knowledge over proxy + +[curl issue 12641](https://github.com/curl/curl/issues/12641) + +## HTTP/2 frames while in the connection pool kill reuse + +If the server sends HTTP/2 frames (like for example an HTTP/2 PING frame) to +curl while the connection is held in curl's connection pool, the socket is +found readable when considered for reuse and that makes curl think it is dead +and then it is closed and a new connection gets created instead. + +This is *best* fixed by adding monitoring to connections while they are kept +in the pool so that pings can be responded to appropriately. + +## `ENHANCE_YOUR_CALM` causes infinite retries + +Infinite retries with 2 parallel requests on one connection receiving `GOAWAY` +with `ENHANCE_YOUR_CALM` error code. + +See [curl issue 5119](https://github.com/curl/curl/issues/5119) + +## HTTP/2 + TLS spends a lot of time in recv + +It has been observed that by making the speed limit less accurate we could +improve this performance. (by reverting +[db5c9f4f9e0779](https://github.com/curl/curl/commit/db5c9f4f9e0779b49624752b135281a0717b277b)) +Can we find a golden middle ground? + +See https://curl.se/mail/lib-2024-05/0026.html and +[curl issue 13416](https://github.com/curl/curl/issues/13416) + +# HTTP/3 + +## connection migration does not work + +[curl issue 7695](https://github.com/curl/curl/issues/7695) + +## quiche: QUIC connection is draining + +The transfer ends with error "QUIC connection is draining". + +[curl issue 12037](https://github.com/curl/curl/issues/12037) + +# RTSP + +## Some methods do not support response bodies + +The RTSP implementation is written to assume that a number of RTSP methods +always get responses without bodies, even though there seems to be no +indication in the RFC that this is always the case. + +[curl issue 12414](https://github.com/curl/curl/issues/12414) diff --git a/docs/KNOWN_RISKS.md b/docs/KNOWN_RISKS.md new file mode 100644 index 000000000000..6138df7f2657 --- /dev/null +++ b/docs/KNOWN_RISKS.md @@ -0,0 +1,146 @@ + + +# Known Risks + +This is an incomplete list of known risks when running and using curl and +libcurl. + +# Risks + +## Insecure transfers + +When using curl to perform transfers with protocols that are insecure or the +server identity is unverified, everything that is sent and received can be +intercepted by eavesdroppers and the servers can easily be spoofed by +impostors. + +## Untrusted input + +You should **never** run curl command lines or use curl config files provided +to you from untrusted sources. + +curl can do a lot of things, and you should only ask it do things you want and +deem correct. + +Even just accepting just the URL part without careful vetting might make curl +do things you do not like. Like accessing internal hosts, like connecting to +rogue servers that redirect to even weirder places, like using ports or +protocols that play tricks on you. + +## Command line misuse + +The command line tool and its options should be used and be expected to work +as documented. Relying on undocumented functions or side-effects is unreliable +as they may cause problems or get changed behavior between releases. + +For several command line options, you can confuse either curl or the involved +server endpoint by using characters or byte sequences for the option that are +not expected. For example, adding line feeds and/or carriage returns to inputs +can produce unexpected, invalid, or insecure results. + +## API misuse + +Applications using the libcurl API in a way that is not documented to work or +even documented to not work, is unsafe and might cause security problems. We +only guarantee secure and proper functionality when the APIs are used as +documented. + +## Local attackers already present + +When there is a local attacker present locally, curl cannot prevent such an +adversary to use curl's full potential. Possibly in malicious ways. + +## Remote attackers already present + +When there is a remote attacker already present in the server, curl cannot +protect its operations against mischief. For example, if an attacker manages +to insert a symlink in your remote upload directory the upload may cause +havoc. Maybe the attacker makes certain responses come back with unexpected +content. + +## Debug & Experiments + +We encourage users to test curl experiments and use debug code, but only in +controlled environments and setups - never in production. + +Using debug builds and experimental curl features in production is a security +risk. Do not do that. + +The same applies to scripts and software which are not installed by default +through the make install rule: they are not intended or made for production +use. + +## URL inconsistencies + +URL parser inconsistencies between browsers and curl are expected and are not +considered security vulnerabilities. The WHATWG URL Specification and RFC +3986+ (the plus meaning that it is an extended version) [are not completely +interoperable](https://github.com/bagder/docs/blob/master/URL-interop.md). + +You must never expect two independent URL parsers to treat every URL +identically. + +## Visible command line arguments + +The curl command blanks the contents of a number of command line arguments to +prevent them from appearing in process listings. It does not blank all +arguments, even though some that are not blanked might contain sensitive data. + + - not all systems allow the arguments to be blanked in the first place + - since curl blanks the argument itself they are readable for a short moment + no matter what + - virtually every argument can contain sensitive data, depending on use + - blanking all arguments would make it impractical for users to differentiate + curl command lines in process listings + +## HTTP headers in redirects + +It is powerful to provide a set of custom headers to curl. Beware that when +asking curl to follow HTTP redirects, it also sends those headers to the new +URL which might be a different server. That might do another redirect etc. + +curl makes some limited attempts to not leak credentials this way when set +using the standard curl options, but when you pass on custom headers curl +cannot know what headers or details in those headers are sensitive. + +## Verbose logs + +When asked to provide verbose output and trace logging, curl may output and +show details that are private and sensitive. Like for example raw credentials +or the password weakly disguised using base64 encoding. + +## 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. 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. + +## Legacy dependencies + +Every curl build is made to use a range of third party libraries. Each third +party library also needs to be safe and secure for the entire operation to be +risk-free. + +Relying on legacy dependencies is a risk. + +## Weak algorithms + +curl supports several cryptographic algorithms that are considered weak, like +DES and MD5. These algorithms are still in use because some protocols and +transfer options require use of them. For example NTLM or legacy HTTP Digest +authentication. + +curl users should consider switching to servers and options that use modern +and secure algorithms. + +## Compression bombs + +When asking curl or libcurl to automatically decompress data on arrival, there +is a risk that the size of the output from the decompression process ends up +many times larger than the input data size. diff --git a/docs/MAIL-ETIQUETTE.md b/docs/MAIL-ETIQUETTE.md index 3de77b17bf7a..4c2f95f38bee 100644 --- a/docs/MAIL-ETIQUETTE.md +++ b/docs/MAIL-ETIQUETTE.md @@ -223,8 +223,7 @@ mails to your friends. We speak plain text mails. ### Quoting Quote as little as possible. Just enough to provide the context you cannot -eave out. A lengthy description can be found -[here](https://www.netmeister.org/news/learn2quote.html). +leave out. ### Digest diff --git a/docs/MANUAL.md b/docs/MANUAL.md index 9ff5c097c7f7..c52e231bdc47 100644 --- a/docs/MANUAL.md +++ b/docs/MANUAL.md @@ -34,7 +34,7 @@ Get the definition of curl from a dictionary: Fetch two documents at once: - curl ftp://ftp.example.com/ http://www.example.com:8000/ + curl ftp://ftp.example.com/ https://www.example.com:8000/ Get a file off an FTPS server: @@ -71,12 +71,12 @@ Get a file from an SMB server: Get a webpage and store in a local file with a specific name: - curl -o thatpage.html http://www.example.com/ + curl -o thatpage.html https://www.example.com/ 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 fails): - curl -O http://www.example.com/index.html + curl -O https://www.example.com/index.html Fetch two files and store them with their remote names: @@ -115,14 +115,14 @@ matching public key file must be specified using the `--pubkey` option. ### HTTP -curl also supports user and password in HTTP URLs, thus you can pick a file +curl also supports user and password in HTTP(S) URLs. You can download a file like: - curl http://name:passwd@http.server.example/full/path/to/file + curl https://name:passwd@http.server.example/full/path/to/file or specify user and password separately like in - curl -u name:passwd http://http.server.example/full/path/to/file + curl -u name:passwd https://http.server.example/full/path/to/file HTTP offers many different methods of authentication and curl supports several: Basic, Digest, NTLM and Negotiate (SPNEGO). Without telling which @@ -151,19 +151,19 @@ Get an ftp file using an HTTP proxy named my-proxy that uses port 888: curl -x my-proxy:888 ftp://ftp.example.com/README -Get a file from an HTTP server that requires user and password, using the +Get a file from an HTTPS server that requires user and password, using the same proxy as above: - curl -u user:passwd -x my-proxy:888 http://www.example.com/ + curl -u user:passwd -x my-proxy:888 https://www.example.com/ Some proxies require special authentication. Specify by using -U as above: - curl -U user:passwd -x my-proxy:888 http://www.example.com/ + curl -U user:passwd -x my-proxy:888 https://www.example.com/ A comma-separated list of hosts and domains which do not use the proxy can be specified as: - curl --noproxy example.com -x my-proxy:888 http://www.example.com/ + curl --noproxy example.com -x my-proxy:888 https://www.example.com/ If the proxy is specified with `--proxy1.0` instead of `--proxy` or `-x`, then curl uses HTTP/1.0 instead of HTTP/1.1 for any `CONNECT` attempts. @@ -204,11 +204,11 @@ one or more sub-parts of a specified document. curl supports this with the Get the first 100 bytes of a document: - curl -r 0-99 http://www.example.com/ + curl -r 0-99 https://www.example.com/ Get the last 500 bytes of a document: - curl -r -500 http://www.example.com/ + curl -r -500 https://www.example.com/ curl also supports simple ranges for FTP files as well. Then you can only specify start and stop position. @@ -251,9 +251,9 @@ fashion similar to: ### HTTP -Upload all data on stdin to a specified HTTP site: +Upload all data on stdin to a specified HTTPS site: - curl -T - http://www.example.com/myfile + curl -T - https://www.example.com/myfile Note that the HTTP server must have been configured to accept PUT before this can be done successfully. @@ -276,7 +276,6 @@ this: curl --trace my-trace.txt www.haxx.se - ## Detailed Information Different protocols provide different ways of getting detailed information @@ -305,12 +304,12 @@ The post data must be urlencoded. Post a simple `name` and `phone` guestbook. - curl -d "name=Rafael%20Sagula&phone=3320780" http://www.example.com/guest.cgi + curl -d "name=Rafael%20Sagula&phone=3320780" https://www.example.com/guest.cgi Or automatically [URL encode the data](https://everything.curl.dev/http/post/url-encode). curl --data-urlencode "name=Rafael Sagula&phone=3320780" - http://www.example.com/guest.cgi + https://www.example.com/guest.cgi How to post a form with curl, lesson #1: @@ -329,7 +328,7 @@ of the letter's ASCII code. Example: -(say if `http://example.com` had the following html) +(say if `https://example.com` had the following html) ```html
@@ -345,7 +344,7 @@ We want to enter user `foobar` with password `12345`. To post to this, you would enter a curl command line like: curl -d "user=foobar&pass=12345&id=blablabla&ding=submit" - http://example.com/post.cgi + https://example.com/post.cgi While `-d` uses the application/x-www-form-urlencoded mime-type, generally understood by CGI's and similar, curl also supports the more capable @@ -359,7 +358,7 @@ example, the field name `coolfiles` is used to send three files, with different content types using the following syntax: curl -F "coolfiles=@fil1.gif;type=image/gif,fil2.txt,fil3.html" - http://www.example.com/postit.cgi + https://www.example.com/postit.cgi If the content-type is not specified, curl tries to guess from the file extension (it only knows a few), or use the previously specified type (from an @@ -376,7 +375,7 @@ the names of the input fields. In our example, the input field names are curl -F "file=@cooltext.txt" -F "yourname=Daniel" -F "filedescription=Cool text file with cool text inside" - http://www.example.com/postit.cgi + https://www.example.com/postit.cgi To send two files in one post you can do it in two ways: @@ -402,7 +401,7 @@ used on the command line. It is especially useful to fool or trick stupid servers or CGI scripts that rely on that information being available or contain certain data. - curl -e www.example.org http://www.example.com/ + curl -e www.example.org https://www.example.com/ ## User Agent @@ -413,7 +412,7 @@ accept certain browsers. Example: - curl -A 'Mozilla/3.0 (Win95; I)' http://www.bank.example.com/ + curl -A 'Mozilla/3.0 (Win95; I)' https://www.bank.example.com/ Other common strings: @@ -596,14 +595,14 @@ Force curl to get and display a local help page in case it is invoked without URL by making a config file similar to: # default url to get - url = "http://help.with.curl.example.com/curlhelp.html" + url = "https://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 filename to `-` it reads the config from stdin, which can be handy if you want to hide options from being visible in process tables etc: - echo "user = user:passwd" | curl -K - http://that.secret.example.com + echo "user = user:passwd" | curl -K - https://that.secret.example.com ## Extra Headers @@ -685,11 +684,11 @@ Download with `PORT` but use 192.168.0.10 as our IP address to use: Get a webpage from a server using a specified port for the interface: - curl --interface eth0:1 http://www.example.com/ + curl --interface eth0:1 https://www.example.com/ or - curl --interface 192.168.1.10 http://www.example.com/ + curl --interface 192.168.1.10 https://www.example.com/ ## HTTPS @@ -740,7 +739,7 @@ Continue uploading a document: Continue downloading a document from a web server - curl -C - -o file http://www.example.com/ + curl -C - -o file https://www.example.com/ ## Time Conditions @@ -751,17 +750,17 @@ them with the `-z`/`--time-cond` flag. For example, you can easily make a download that only gets performed if the remote file is newer than a local copy. It would be made like: - curl -z local.html http://remote.example.com/remote.html + curl -z local.html https://remote.example.com/remote.html Or you can download a file only if the local file is newer than the remote one. Do this by prepending the date string with a `-`, as in: - curl -z -local.html http://remote.example.com/remote.html + curl -z -local.html https://remote.example.com/remote.html You can specify a plain text date as condition. Tell curl to only download the file if it was updated since January 12, 2012: - curl -z "Jan 12 2012" http://remote.example.com/remote.html + curl -z "Jan 12 2012" https://remote.example.com/remote.html curl accepts a wide range of date formats. You always make the date check the other way around by prepending it with a dash (`-`). @@ -944,7 +943,7 @@ URL you specify. Note that this also goes for the `-O` option (but not For example: get two files and use `-O` for the first and a custom file name for the second: - curl -O http://example.com/file.txt ftp://example.com/moo.exe -o moo.jpg + curl -O https://example.com/file.txt ftp://example.com/moo.exe -o moo.jpg You can also upload multiple files in a similar fashion: @@ -957,7 +956,7 @@ and fall back to IPv4 if the connection fails. The `--ipv4` and `--ipv6` options can specify which address to use when both are available. IPv6 addresses can also be specified directly in URLs using the syntax: - http://[2001:1890:1112:1::20]/overview.html + https://[2001:1890:1112:1::20]/overview.html When this style is used, the `-g` option must be given to stop curl from interpreting the square brackets as special globbing characters. Link local diff --git a/docs/Makefile.am b/docs/Makefile.am index 65ba28c0eb50..c0c25232b826 100644 --- a/docs/Makefile.am +++ b/docs/Makefile.am @@ -63,10 +63,12 @@ INTERNALDOCS = \ internals/MULTI-EV.md \ internals/NEW-PROTOCOL.md \ internals/PORTING.md \ + internals/RATELIMITS.md \ internals/README.md \ internals/SCORECARD.md \ internals/SPLAY.md \ internals/STRPARSE.md \ + internals/TIME-KEEPING.md \ internals/TLS-SESSIONS.md \ internals/UINT_SETS.md \ internals/WEBSOCKET.md @@ -92,7 +94,7 @@ EXTRA_DIST = \ EARLY-RELEASE.md \ ECH.md \ EXPERIMENTAL.md \ - FAQ \ + FAQ.md \ FEATURES.md \ GOVERNANCE.md \ HELP-US.md \ @@ -107,7 +109,8 @@ EXTRA_DIST = \ INSTALL.md \ INTERNALS.md \ IPFS.md \ - KNOWN_BUGS \ + KNOWN_BUGS.md \ + KNOWN_RISKS.md \ MAIL-ETIQUETTE.md \ MANUAL.md \ options-in-versions \ @@ -119,7 +122,8 @@ EXTRA_DIST = \ SPONSORS.md \ SSL-PROBLEMS.md \ SSLCERTS.md \ - THANKS TODO \ + THANKS \ + TODO.md \ TheArtOfHttpScripting.md \ URL-SYNTAX.md \ VERSIONS.md \ diff --git a/docs/SSLCERTS.md b/docs/SSLCERTS.md index de3954553421..3506fbd787d1 100644 --- a/docs/SSLCERTS.md +++ b/docs/SSLCERTS.md @@ -133,7 +133,6 @@ Apple SecTrust and your own file to be considered, use: curl --ca-native --cacert mycerts.pem https://example.com - #### Other Combinations How well the use of native CA stores work in all other combinations depends diff --git a/docs/THANKS b/docs/THANKS index 97f9999b080a..d3b3efc0f11f 100644 --- a/docs/THANKS +++ b/docs/THANKS @@ -88,6 +88,7 @@ Alessandro Vesely Alex aka WindEagle Alexander Bartel Alexander Beedie +Alexander Blach Alexander Chuykov Alexander Dyagilev Alexander Elgert @@ -221,6 +222,7 @@ Andrew Krieger Andrew Kurushin Andrew Lambert Andrew Moise +Andrew Olsen Andrew Potter Andrew Robbins Andrew Wansink @@ -238,6 +240,7 @@ Andy Reitz Andy Serpa Andy Stamp Andy Tsouladze +And-yW on github Angus Mackay anio on github annalee @@ -358,7 +361,7 @@ Benjamin Sergeant Ben Kohler Ben Madsen Ben Noordhuis -Benoit Neil +Benoit Neil (Sukender) Benoit Pierre Benoit Sigoure Ben Van Hof @@ -411,6 +414,7 @@ Bob Richmond Bob Schader Bodo Bergmann Bogdan Nicula +BohwaZ boilingoden Boris Kuschel Boris Okunskiy @@ -636,6 +640,7 @@ Cristian Greco Cristian Morales Vega Cristian Rodríguez CueXXIII on github +curl.stunt430 Curt Bogmine Cynthia Coan Cyril B @@ -649,6 +654,7 @@ Dagfinn Ilmari Mannsåker Dagobert Michelsen Daiki Ueno Dair Grant +Dalei Dambaev Alexander Damian Dixon Damien Adant @@ -694,6 +700,7 @@ Daniel Silverstone Daniel Steinberg Daniel Stenberg Daniel Szmulewicz +Daniel Terhorst-North Daniel Theron Daniel Valenzuela Daniel Woelfel @@ -804,6 +811,7 @@ Derzsi Dániel Desmond O. Chang destman on github Detlef Schmier +Devdatta Talele devgs on github Dexter Gerig dfdity on github @@ -948,10 +956,12 @@ Emil Engler Emiliano Ida Emilio Cobos Álvarez Emilio López +Emilio Pozuelo Monfort Emil Lerner Emil Österlund Emil Romanus Emmanuel Tychon +Emre Çalışkan Enno Boland Enrico Scholz Enrik Berkhan @@ -1200,6 +1210,7 @@ Guillaume Algis Guillaume Arluison guitared on github Gunamoi Software +Gunni on github Gunter Knauf guoxinvmware on github Gustaf Hui @@ -1303,6 +1314,7 @@ IcedCoffeee on github iconoclasthero icy17 on github Ignacio Vazquez-Abrams +Ignat Loskutov Igor Franchuk Igor Khristophorov Igor Makarov @@ -1367,6 +1379,7 @@ jakirkham on github Jakob Hirsch Jakub Bochenski Jakub Jelen +Jakub Stasiak Jakub Wilk Jakub Zakrzewski James Abbatiello @@ -1503,6 +1516,7 @@ jhoyla on github Jiacai Liu Jiang Wenjian Jiawen Geng +Jicea Jie He Jiehong on github Jilayne Lovejoy @@ -1524,6 +1538,7 @@ Jishan Shaikh Jiwoo Park Jixinqi jkamp-aws on github +jmaggard10 on github jmdavitt on github jnbr on github Jocelyn Jaubert @@ -1635,6 +1650,7 @@ Jose Alf Josef Wolf José Joaquín Atria Jose Kahan +Joseph Birr-Pixton Joseph Chen Joseph Tharayil Josh Bialkowski @@ -1645,6 +1661,7 @@ Josh Kapell Josh McCullough Josh Soref Joshua Kwan +Joshua Rogers Joshua Root Joshua Swink Josie Huddleston @@ -1709,6 +1726,7 @@ Kane York Kang-Jin Lee Kang Lin Kantanat Wannapaka +kapsiR on github Kareem Kari Pahula Karl Chen @@ -1800,6 +1818,7 @@ Kristoffer Gleditsch kriztalz K. R. Walker Kuan-Wei Chiu +kuchara on github Kunal Chandarana Kunal Ekawde kupavcevdenis on github @@ -1948,6 +1967,7 @@ Maciej Puzio Maciej W. Rozycki MacKenzie madblobfish on github +madoe on github MaeIsBad on github magisterquis on hackerone Mahmoud Samir Fayed @@ -2241,6 +2261,7 @@ Mingtao Yang Miroslav Franc Miroslav Spousta Mischa Salle +Mitchell Blank Jr Mitz Wark mkzero on github modbw on github @@ -2363,6 +2384,7 @@ Ning Dong NINIKA Niracler Li Niranjan Hasabnis +Nir Azkiel Nir Soffer Nis Jorgensen nk @@ -2489,6 +2511,7 @@ Pavel Kropachev Pavel Löbl Pavel Mayorov Pavel Orehov +Pavel P Pavel Pavlov Pavel Raiskup Pavel Rochnyak @@ -2507,6 +2530,7 @@ Pedro Neves pendrek at hackerone Peng Li Peng-Yu Chen +pennae on github Per Jensen Per Lundberg Per Malmberg @@ -2586,7 +2610,9 @@ Piotr Dobrogost Piotr Komborski Piotr Nakraszewicz PleaseJustDont +plv1313 on github Po-Chuan Hsieh +Pocs Norbert Pontakorn Prasertsuk Pontus Lundkvist Pooyan McSporran @@ -2738,6 +2764,7 @@ Rider Linden Rikard Falkeborn rilysh Rinku Das +rinsuki on github rl1987 on github rmg-x on github rm-rmonaghan on github @@ -2843,6 +2870,7 @@ rzrymiak on github s0urc3_ on hackerone saimen Sai Ram Kunala +Sakthi SK Salah-Eddin Shaban Saleem Abdulrasool SaltyMilk @@ -3007,6 +3035,7 @@ sspiri on github sstruchtrup on github Stadler Stephan Stan Hu +Stanislav Fort Stanislav Ivochkin Stanislav Lange Stanislav Osipov @@ -3119,11 +3148,14 @@ Temprimus Terence Eden Terri Oda Terry Wu +Tetetest thanhchungbtc on github TheAssassin on github +TheBitBrine The Infinnovation team TheKnarf on github Theo +Theo Buehler Theodore A. Roth Theodore Dubois therealhirudo on github @@ -3162,6 +3194,7 @@ Till Wegmüller Tim Ansell Tim Baker Tim Bartley +Tim Becker Tim Chen Tim Costello Tim Harder @@ -3296,6 +3329,7 @@ UrsusArctos on github User Sg ustcqidi on github Vadim Grinshpun +Vaibhav Kumar Valentin David Valentín Gutiérrez Valentin Richter @@ -3363,6 +3397,7 @@ w0x42 on hackerone Waldek Kozba Waldemar Kornewald Walter J. Mack +WangDaLei on github wangzhikun Ward Willats Warren Menzer @@ -3499,6 +3534,7 @@ zzq1015 on github ウさん 不确定 加藤郁之 +包布丁 南宫雪珊 左潇峰 李四 diff --git a/docs/THANKS-filter b/docs/THANKS-filter index fd8722da8bcc..501b649f7632 100644 --- a/docs/THANKS-filter +++ b/docs/THANKS-filter @@ -160,3 +160,4 @@ s/jethrogb$/jethrogb on github/ s/on github/on github/i s/Maksim Sciepanienka/Maksim Ściepanienka/ s/Qriist.*/Qriist on github/ +s/Viktor Szakatas/Viktor Szakats/ diff --git a/docs/TODO b/docs/TODO deleted file mode 100644 index 6c3ba904e721..000000000000 --- a/docs/TODO +++ /dev/null @@ -1,1283 +0,0 @@ - _ _ ____ _ - ___| | | | _ \| | - / __| | | | |_) | | - | (__| |_| | _ <| |___ - \___|\___/|_| \_\_____| - - Things that could be nice to do in the future - - Things to do in project curl. Please tell us what you think, contribute and - send us patches that improve things. - - Be aware that these are things that we could do, or have once been considered - things we could do. If you want to work on any of these areas, please - consider bringing it up for discussions first on the mailing list so that we - all agree it is still a good idea for the project. - - All bugs documented in the KNOWN_BUGS document are subject for fixing. - - 1. libcurl - 1.1 TFO support on Windows - 1.2 Consult %APPDATA% also for .netrc - 1.3 struct lifreq - 1.4 alt-svc sharing - 1.5 get rid of PATH_MAX - 1.6 thread-safe sharing - 1.10 auto-detect proxy - 1.12 updated DNS server while running - 1.13 c-ares and CURLOPT_OPENSOCKETFUNCTION - 1.15 Monitor connections in the connection pool - 1.16 Try to URL encode given URL - 1.17 Add support for IRIs - 1.18 try next proxy if one does not work - 1.19 provide timing info for each redirect - 1.20 SRV and URI DNS records - 1.22 CURLINFO_PAUSE_STATE - 1.25 Expose tried IP addresses that failed - 1.30 config file parsing - 1.31 erase secrets from heap/stack after use - 1.32 add asynch getaddrinfo support - 1.33 make DoH inherit more transfer properties - - 2. libcurl - multi interface - 2.1 More non-blocking - 2.2 Better support for same name resolves - 2.3 Non-blocking curl_multi_remove_handle() - 2.4 Split connect and authentication process - 2.5 Edge-triggered sockets should work - 2.6 multi upkeep - 2.7 Virtual external sockets - 2.8 dynamically decide to use socketpair - - 3. Documentation - 3.1 Improve documentation about fork safety - - 4. FTP - 4.1 HOST - 4.6 GSSAPI via Windows SSPI - 4.7 STAT for LIST without data connection - 4.8 Passive transfer could try other IP addresses - - 5. HTTP - 5.1 Provide the error body from a CONNECT response - 5.2 Obey Retry-After in redirects - 5.3 Rearrange request header order - 5.4 Allow SAN names in HTTP/2 server push - 5.5 auth= in URLs - 5.6 alt-svc should fallback if alt-svc does not work - 5.7 Require HTTP version X or higher - - 6. TELNET - 6.1 ditch stdin - 6.2 ditch telnet-specific select - 6.3 feature negotiation debug data - 6.4 exit immediately upon connection if stdin is /dev/null - - 7. SMTP - 7.1 Passing NOTIFY option to CURLOPT_MAIL_RCPT - 7.2 Enhanced capability support - 7.3 Add CURLOPT_MAIL_CLIENT option - - 8. POP3 - 8.2 Enhanced capability support - - 9. IMAP - 9.1 Enhanced capability support - - 10. LDAP - 10.1 SASL based authentication mechanisms - 10.2 CURLOPT_SSL_CTX_FUNCTION for LDAPS - 10.3 Paged searches on LDAP server - 10.4 Certificate-Based Authentication - - 11. SMB - 11.1 File listing support - 11.2 Honor file timestamps - 11.3 Use NTLMv2 - 11.4 Create remote directories - - 12. FILE - 12.1 Directory listing on non-POSIX - - 13. TLS - 13.1 TLS-PSK with OpenSSL - 13.2 TLS channel binding - 13.3 Defeat TLS fingerprinting - 13.4 Consider OCSP stapling by default - 13.6 Provide callback for cert verification - 13.7 Less memory massaging with Schannel - 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.13 Make sure we forbid TLS 1.3 post-handshake authentication - 13.14 Support the clienthello extension - 13.16 Share the CA cache - 13.17 Add missing features to TLS backends - - 14. Proxy - 14.1 Retry SOCKS handshake on address type not supported - - 15. Schannel - 15.1 Extend support for client certificate authentication - 15.2 Extend support for the --ciphers option - 15.4 Add option to allow abrupt server closure - - 16. SASL - 16.1 Other authentication mechanisms - 16.2 Add QOP support to GSSAPI authentication - - 17. SSH protocols - 17.1 Multiplexing - 17.2 Handle growing SFTP files - 17.3 Read keys from ~/.ssh/id_ecdsa, id_ed25519 - 17.4 Support CURLOPT_PREQUOTE - 17.5 SSH over HTTPS proxy with more backends - 17.6 SFTP with SCP:// - - 18. Command line tool - 18.1 sync - 18.2 glob posts - 18.4 --proxycommand - 18.5 UTF-8 filenames in Content-Disposition - 18.6 Option to make -Z merge lined based outputs on stdout - 18.7 specify which response codes that make -f/--fail return error - 18.9 Choose the name of file in braces for complex URLs - 18.10 improve how curl works in a Windows console window - 18.11 Windows: set attribute 'archive' for completed downloads - 18.12 keep running, read instructions from pipe/socket - 18.13 Acknowledge Ratelimit headers - 18.14 --dry-run - 18.15 --retry should resume - 18.17 consider filename from the redirected URL with -O ? - 18.18 retry on network is unreachable - 18.20 hostname sections in config files - 18.21 retry on the redirected-to URL - 18.23 Set the modification date on an uploaded file - 18.24 Use multiple parallel transfers for a single download - 18.25 Prevent terminal injection when writing to terminal - 18.26 Custom progress meter update interval - 18.27 -J and -O with %-encoded filenames - 18.28 -J with -C - - 18.29 --retry and transfer timeouts - - 19. Build - 19.2 Enable PIE and RELRO by default - 19.3 Do not use GNU libtool on OpenBSD - 19.4 Package curl for Windows in a signed installer - 19.5 make configure use --cache-file more and better - - 20. Test suite - 20.1 SSL tunnel - 20.2 more protocols supported - 20.3 more platforms supported - 20.4 write an SMB test server to replace impacket - 20.5 Use the RFC 6265 test suite - 20.6 Run web-platform-tests URL tests - - 21. MQTT - 21.1 Support rate-limiting - 21.2 Support MQTTS - 21.3 Handle network blocks - - 22. TFTP - 22.1 TFTP does not convert LF to CRLF for mode=netascii - - 23. Gopher - 23.1 Handle network blocks - -============================================================================== - -1. libcurl - -1.1 TFO support on Windows - - libcurl supports the CURLOPT_TCP_FASTOPEN option since 7.49.0 for Linux and - macOS. Windows supports TCP Fast Open starting with Windows 10, version 1607 - and we should add support for it. - - TCP Fast Open is supported on several platforms but not on Windows. Work on - this was once started but never finished. - - See https://github.com/curl/curl/pull/3378 - -1.2 Consult %APPDATA% also for .netrc - - %APPDATA%\.netrc is not considered when running on Windows. should not it? - - See https://github.com/curl/curl/issues/4016 - -1.3 struct lifreq - - Use 'struct lifreq' and SIOCGLIFADDR instead of 'struct ifreq' and - SIOCGIFADDR on newer Solaris versions as they claim the latter is obsolete. - To support IPv6 interface addresses for network interfaces properly. - -1.4 alt-svc sharing - - The share interface could benefit from allowing the alt-svc cache to be - possible to share between easy handles. - - See https://github.com/curl/curl/issues/4476 - - The share interface offers CURL_LOCK_DATA_CONNECT to have multiple easy - handle share a connection cache, but due to how connections are used they are - still not thread-safe when used shared. - - See https://github.com/curl/curl/issues/4915 and lib1541.c - - The share interface offers CURL_LOCK_DATA_HSTS to have multiple easy handle - share an HSTS cache, but this is not thread-safe. - -1.5 get rid of PATH_MAX - - Having code use and rely on PATH_MAX is not nice: - https://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html - - Currently the libssh2 SSH based code uses it, but to remove PATH_MAX from - there we need libssh2 to properly tell us when we pass in a too small buffer - and its current API (as of libssh2 1.2.7) does not. - -1.6 thread-safe sharing - - Using the share interface users can share some data between easy handles but - several of the sharing options are documented as not safe and supported to - share between multiple concurrent threads. Fixing this would enable more - users to share data in more powerful ways. - -1.10 auto-detect proxy - - libcurl could be made to detect the system proxy setup automatically and use - that. On Windows, macOS and Linux desktops for example. - - The pull-request to use libproxy for this was deferred due to doubts on the - reliability of the dependency and how to use it: - https://github.com/curl/curl/pull/977 - - libdetectproxy is a (C++) library for detecting the proxy on Windows - https://github.com/paulharris/libdetectproxy - -1.12 updated DNS server while running - - If /etc/resolv.conf gets updated while a program using libcurl is running, it - is may cause name resolves to fail unless res_init() is called. We should - consider calling res_init() + retry once unconditionally on all name resolve - failures to mitigate against this. Firefox works like that. Note that Windows - does not have res_init() or an alternative. - - https://github.com/curl/curl/issues/2251 - -1.13 c-ares and CURLOPT_OPENSOCKETFUNCTION - - curl creates most sockets via the CURLOPT_OPENSOCKETFUNCTION callback and - close them with the CURLOPT_CLOSESOCKETFUNCTION callback. However, c-ares - does not use those functions and instead opens and closes the sockets itself. - This means that when curl passes the c-ares socket to the - CURLMOPT_SOCKETFUNCTION it is not owned by the application like other - sockets. - - See https://github.com/curl/curl/issues/2734 - -1.15 Monitor connections in the connection pool - - libcurl's connection cache or pool holds a number of open connections for the - purpose of possible subsequent connection reuse. It may contain a few up to a - significant amount of connections. Currently, libcurl leaves all connections - as they are and first when a connection is iterated over for matching or - reuse purpose it is verified that it is still alive. - - Those connections may get closed by the server side for idleness or they may - get an HTTP/2 ping from the peer to verify that they are still alive. By - adding monitoring of the connections while in the pool, libcurl can detect - dead connections (and close them) better and earlier, and it can handle - HTTP/2 pings to keep such ones alive even when not actively doing transfers - on them. - -1.16 Try to URL encode given URL - - Given a URL that for example contains spaces, libcurl could have an option - that would try somewhat harder than it does now and convert spaces to %20 and - perhaps URL encoded byte values over 128 etc (basically do what the redirect - following code already does). - - https://github.com/curl/curl/issues/514 - -1.17 Add support for IRIs - - IRIs (RFC 3987) allow localized, non-ASCII, names in the URL. To properly - support this, curl/libcurl would need to translate/encode the given input - from the input string encoding into percent encoded output "over the wire". - - To make that work smoothly for curl users even on Windows, curl would - probably need to be able to convert from several input encodings. - -1.18 try next proxy if one does not work - - Allow an application to specify a list of proxies to try, and failing to - connect to the first go on and try the next instead until the list is - exhausted. Browsers support this feature at least when they specify proxies - using PACs. - - https://github.com/curl/curl/issues/896 - -1.19 provide timing info for each redirect - - curl and libcurl provide timing information via a set of different - time-stamps (CURLINFO_*_TIME). When curl is following redirects, those - returned time value are the accumulated sums. An improvement could be to - offer separate timings for each redirect. - - https://github.com/curl/curl/issues/6743 - -1.20 SRV and URI DNS records - - Offer support for resolving SRV and URI DNS records for libcurl to know which - server to connect to for various protocols (including HTTP). - -1.22 CURLINFO_PAUSE_STATE - - Return information about the transfer's current pause state, in both - directions. https://github.com/curl/curl/issues/2588 - -1.25 Expose tried IP addresses that failed - - When libcurl fails to connect to a host, it could offer the application the - addresses that were used in the attempt. Source + dest IP, source + dest port - and protocol (UDP or TCP) for each failure. Possibly as a callback. Perhaps - also provide "reason". - - https://github.com/curl/curl/issues/2126 - -1.30 config file parsing - - Consider providing an API, possibly in a separate companion library, for - parsing a config file like curl's -K/--config option to allow applications to - get the same ability to read curl options from files. - - See https://github.com/curl/curl/issues/3698 - -1.31 erase secrets from heap/stack after use - - Introducing a concept and system to erase secrets from memory after use, it - could help mitigate and lessen the impact of (future) security problems etc. - However: most secrets are passed to libcurl as clear text from the - application and then clearing them within the library adds nothing... - - https://github.com/curl/curl/issues/7268 - -1.32 add asynch getaddrinfo support - - Use getaddrinfo_a() to provide an asynch name resolver backend to libcurl - that does not use threads and does not depend on c-ares. The getaddrinfo_a - function is (probably?) glibc specific but that is a widely used libc among - our users. - - https://github.com/curl/curl/pull/6746 - -1.33 make DoH inherit more transfer properties - - Some options are not inherited because they are not relevant for the DoH SSL - connections, or inheriting the option may result in unexpected behavior. For - example the user's debug function callback is not inherited because it would - be unexpected for internal handles (ie DoH handles) to be passed to that - callback. - - If an option is not inherited then it is not possible to set it separately - for DoH without a DoH-specific option. For example: - CURLOPT_DOH_SSL_VERIFYHOST, CURLOPT_DOH_SSL_VERIFYPEER and - CURLOPT_DOH_SSL_VERIFYSTATUS. - - See https://github.com/curl/curl/issues/6605 - -2. libcurl - multi interface - -2.1 More non-blocking - - Make sure we do not ever loop because of non-blocking sockets returning - EWOULDBLOCK or similar. Blocking cases include: - - - Name resolves on non-Windows unless c-ares or the threaded resolver is used. - - - The threaded resolver may block on cleanup: - https://github.com/curl/curl/issues/4852 - - - file:// transfers - - - TELNET transfers - - - GSSAPI authentication for FTP transfers - - - The "DONE" operation (post transfer protocol-specific actions) for the - protocols SFTP, SMTP, FTP. Fixing multi_done() for this is a worthy task. - - - curl_multi_remove_handle for any of the above. See section 2.3. - - - Calling curl_ws_send() from a callback - -2.2 Better support for same name resolves - - If a name resolve has been initiated for name NN and a second easy handle - wants to resolve that name as well, make it wait for the first resolve to end - up in the cache instead of doing a second separate resolve. This is - especially needed when adding many simultaneous handles using the same host - name when the DNS resolver can get flooded. - -2.3 Non-blocking curl_multi_remove_handle() - - The multi interface has a few API calls that assume a blocking behavior, like - add_handle() and remove_handle() which limits what we can do internally. The - multi API need to be moved even more into a single function that "drives" - everything in a non-blocking manner and signals when something is done. A - remove or add would then only ask for the action to get started and then - multi_perform() etc still be called until the add/remove is completed. - -2.4 Split connect and authentication process - - The multi interface treats the authentication process as part of the connect - phase. As such any failures during authentication does not trigger the - relevant QUIT or LOGOFF for protocols such as IMAP, POP3 and SMTP. - -2.5 Edge-triggered sockets should work - - The multi_socket API should work with edge-triggered socket events. One of - the internal actions that need to be improved for this to work perfectly is - the 'maxloops' handling in transfer.c:readwrite_data(). - -2.6 multi upkeep - - In libcurl 7.62.0 we introduced curl_easy_upkeep. It unfortunately only works - on easy handles. We should introduces a version of that for the multi handle, - and also consider doing "upkeep" automatically on connections in the - connection pool when the multi handle is in used. - - See https://github.com/curl/curl/issues/3199 - -2.7 Virtual external sockets - - libcurl performs operations on the given file descriptor that presumes it is - a socket and an application cannot replace them at the moment. Allowing an - application to fully replace those would allow a larger degree of freedom and - flexibility. - - See https://github.com/curl/curl/issues/5835 - -2.8 dynamically decide to use socketpair - - For users who do not use curl_multi_wait() or do not care for - curl_multi_wakeup(), we could introduce a way to make libcurl NOT - create a socketpair in the multi handle. - - See https://github.com/curl/curl/issues/4829 - -3. Documentation - -3.1 Improve documentation about fork safety - - See https://github.com/curl/curl/issues/6968 - -4. FTP - -4.1 HOST - - HOST is a command for a client to tell which hostname to use, to offer FTP - servers named-based virtual hosting: - - https://datatracker.ietf.org/doc/html/rfc7151 - -4.6 GSSAPI via Windows SSPI - - In addition to currently supporting the SASL GSSAPI mechanism (Kerberos V5) - via third-party GSS-API libraries, such as MIT Kerberos, also add support - for GSSAPI authentication via Windows SSPI. - -4.7 STAT for LIST without data connection - - Some FTP servers allow STAT for listing directories instead of using LIST, - and the response is then sent over the control connection instead of as the - otherwise usedw data connection: https://www.nsftools.com/tips/RawFTP.htm#STAT - - This is not detailed in any FTP specification. - -4.8 Passive transfer could try other IP addresses - - When doing FTP operations through a proxy at localhost, the reported spotted - that curl only tried to connect once to the proxy, while it had multiple - addresses and a failed connect on one address should make it try the next. - - After switching to passive mode (EPSV), curl could try all IP addresses for - "localhost". Currently it tries ::1, but it should also try 127.0.0.1. - - See https://github.com/curl/curl/issues/1508 - -5. HTTP - -5.1 Provide the error body from a CONNECT response - - When curl receives a body response from a CONNECT request to a proxy, it - always just reads and ignores it. It would make some users happy if curl - instead optionally would be able to make that responsible available. Via a - new callback? Through some other means? - - See https://github.com/curl/curl/issues/9513 - -5.2 Obey Retry-After in redirects - - The Retry-After is said to dictate "the minimum time that the user agent is - asked to wait before issuing the redirected request" and libcurl does not - obey this. - - See https://github.com/curl/curl/issues/11447 - -5.3 Rearrange request header order - - Server implementers often make an effort to detect browser and to reject - clients it can detect to not match. One of the last details we cannot yet - control in libcurl's HTTP requests, which also can be exploited to detect - that libcurl is in fact used even when it tries to impersonate a browser, is - the order of the request headers. I propose that we introduce a new option in - which you give headers a value, and then when the HTTP request is built it - sorts the headers based on that number. We could then have internally created - headers use a default value so only headers that need to be moved have to be - specified. - -5.4 Allow SAN names in HTTP/2 server push - - curl only allows HTTP/2 push promise if the provided :authority header value - exactly matches the hostname given in the URL. It could be extended to allow - any name that would match the Subject Alternative Names in the server's TLS - certificate. - - See https://github.com/curl/curl/pull/3581 - -5.5 auth= in URLs - - Add the ability to specify the preferred authentication mechanism to use by - using ;auth= in the login part of the URL. - - For example: - - http://test:pass;auth=NTLM@example.com would be equivalent to specifying - --user test:pass;auth=NTLM or --user test:pass --ntlm from the command line. - - Additionally this should be implemented for proxy base URLs as well. - -5.6 alt-svc should fallback if alt-svc does not work - - The alt-svc: header provides a set of alternative services for curl to use - instead of the original. If the first attempted one fails, it should try the - next etc and if all alternatives fail go back to the original. - - See https://github.com/curl/curl/issues/4908 - -5.7 Require HTTP version X or higher - - curl and libcurl provide options for trying higher HTTP versions (for example - HTTP/2) but then still allows the server to pick version 1.1. We could - consider adding a way to require a minimum version. - - See https://github.com/curl/curl/issues/7980 - -6. TELNET - -6.1 ditch stdin - - Reading input (to send to the remote server) on stdin is a crappy solution - for library purposes. We need to invent a good way for the application to be - able to provide the data to send. - -6.2 ditch telnet-specific select - - Move the telnet support's network select() loop go away and merge the code - into the main transfer loop. Until this is done, the multi interface does not - work for telnet. - -6.3 feature negotiation debug data - - Add telnet feature negotiation data to the debug callback as header data. - -6.4 exit immediately upon connection if stdin is /dev/null - - If it did, curl could be used to probe if there is an server there listening - on a specific port. That is, the following command would exit immediately - after the connection is established with exit code 0: - - curl -s --connect-timeout 2 telnet://example.com:80 NOTIFY=SUCCESS,FAILURE" ); - - https://github.com/curl/curl/issues/8232 - -7.2 Enhanced capability support - - Add the ability, for an application that uses libcurl, to obtain the list of - capabilities returned from the EHLO command. - -7.3 Add CURLOPT_MAIL_CLIENT option - - Rather than use the URL to specify the mail client string to present in the - HELO and EHLO commands, libcurl should support a new CURLOPT specifically for - specifying this data as the URL is non-standard and to be honest a bit of a - hack ;-) - - Please see the following thread for more information: - https://curl.se/mail/lib-2012-05/0178.html - - -8. POP3 - -8.2 Enhanced capability support - - Add the ability, for an application that uses libcurl, to obtain the list of - capabilities returned from the CAPA command. - -9. IMAP - -9.1 Enhanced capability support - - Add the ability, for an application that uses libcurl, to obtain the list of - capabilities returned from the CAPABILITY command. - -10. LDAP - -10.1 SASL based authentication mechanisms - - Currently the LDAP module only supports ldap_simple_bind_s() in order to bind - to an LDAP server. However, this function sends username and password details - using the simple authentication mechanism (as clear text). However, it should - be possible to use ldap_bind_s() instead specifying the security context - information ourselves. - -10.2 CURLOPT_SSL_CTX_FUNCTION for LDAPS - - CURLOPT_SSL_CTX_FUNCTION works perfectly for HTTPS and email protocols, but - it has no effect for LDAPS connections. - - https://github.com/curl/curl/issues/4108 - -10.3 Paged searches on LDAP server - - https://github.com/curl/curl/issues/4452 - -10.4 Certificate-Based Authentication - - LDAPS not possible with macOS and Windows with Certificate-Based Authentication - - https://github.com/curl/curl/issues/9641 - -11. SMB - -11.1 File listing support - - Add support for listing the contents of an SMB share. The output should - probably be the same as/similar to FTP. - -11.2 Honor file timestamps - - The timestamp of the transferred file should reflect that of the original - file. - -11.3 Use NTLMv2 - - Currently the SMB authentication uses NTLMv1. - -11.4 Create remote directories - - Support for creating remote directories when uploading a file to a directory - that does not exist on the server, just like --ftp-create-dirs. - - -12. FILE - -12.1 Directory listing on non-POSIX - - Listing the contents of a directory accessed with FILE only works on - platforms with opendir. Support could be added for more systems, like - Windows. - -13. TLS - -13.1 TLS-PSK with OpenSSL - - Transport Layer Security pre-shared key ciphersuites (TLS-PSK) is a set of - cryptographic protocols that provide secure communication based on pre-shared - keys (PSKs). These pre-shared keys are symmetric keys shared in advance among - the communicating parties. - - https://github.com/curl/curl/issues/5081 - -13.2 TLS channel binding - - TLS 1.2 and 1.3 provide the ability to extract some secret data from the TLS - connection and use it in the client request (usually in some sort of - authentication) to ensure that the data sent is bound to the specific TLS - connection and cannot be successfully intercepted by a proxy. This - functionality can be used in a standard authentication mechanism such as - GSS-API or SCRAM, or in custom approaches like custom HTTP Authentication - headers. - - For TLS 1.2, the binding type is usually tls-unique, and for TLS 1.3 it is - tls-exporter. - - https://datatracker.ietf.org/doc/html/rfc5929 - https://datatracker.ietf.org/doc/html/rfc9266 - https://github.com/curl/curl/issues/9226 - -13.3 Defeat TLS fingerprinting - - By changing the order of TLS extensions provided in the TLS handshake, it is - sometimes possible to circumvent TLS fingerprinting by servers. The TLS - extension order is of course not the only way to fingerprint a client. - -13.4 Consider OCSP stapling by default - - Treat a negative response a reason for aborting the connection. Since OCSP - stapling is presumed to get used much less in the future when Let's Encrypt - drops the OCSP support, the benefit of this might however be limited. - - https://github.com/curl/curl/issues/15483 - -13.6 Provide callback for cert verification - - OpenSSL supports a callback for customised verification of the peer - certificate, but this does not seem to be exposed in the libcurl APIs. Could - it be? There is so much that could be done if it were. - -13.7 Less memory massaging with Schannel - - The Schannel backend does a lot of custom memory management we would rather - avoid: the repeated alloc + free in sends and the custom memory + realloc - system for encrypted and decrypted data. That should be avoided and reduced - for 1) efficiency and 2) safety. - -13.8 Support DANE - - DNS-Based Authentication of Named Entities (DANE) is a way to provide SSL - keys and certs over DNS using DNSSEC as an alternative to the CA model. - https://www.rfc-editor.org/rfc/rfc6698.txt - - An initial patch was posted by Suresh Krishnaswamy on March 7th 2013 - (https://curl.se/mail/lib-2013-03/0075.html) but it was a too simple - approach. See Daniel's comments: - https://curl.se/mail/lib-2013-03/0103.html . libunbound may be the - correct library to base this development on. - - Björn Stenberg wrote a separate initial take on DANE that was never - completed. - -13.9 TLS record padding - - TLS (1.3) offers optional record padding and OpenSSL provides an API for it. - I could make sense for libcurl to offer this ability to applications to make - traffic patterns harder to figure out by network traffic observers. - - See https://github.com/curl/curl/issues/5398 - -13.10 Support Authority Information Access certificate extension (AIA) - - AIA can provide various things like CRLs but more importantly information - about intermediate CA certificates that can allow validation path to be - fulfilled when the HTTPS server does not itself provide them. - - Since AIA is about downloading certs on demand to complete a TLS handshake, - it is probably a bit tricky to get done right. - - 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. - For more Documentation on this see: - https://curl.se/libcurl/c/tls-options.html - - https://github.com/curl/curl/issues/12286 - -13.13 Make sure we forbid TLS 1.3 post-handshake authentication - - RFC 8740 explains how using HTTP/2 must forbid the use of TLS 1.3 - post-handshake authentication. We should make sure to live up to that. - - See https://github.com/curl/curl/issues/5396 - -13.14 Support the clienthello extension - - Certain stupid networks and middle boxes have a problem with SSL handshake - packets that are within a certain size range because how that sets some bits - that previously (in older TLS version) were not set. The clienthello - extension adds padding to avoid that size range. - - https://datatracker.ietf.org/doc/html/rfc7685 - https://github.com/curl/curl/issues/2299 - -13.16 Share the CA cache - - For TLS backends that supports CA caching, it makes sense to allow the share - object to be used to store the CA cache as well via the share API. Would - allow multiple easy handles to reuse the CA cache and save themselves from a - lot of extra processing overhead. - -13.17 Add missing features to TLS backends - - The feature matrix at https://curl.se/libcurl/c/tls-options.html shows which - features are supported by which TLS backends, and thus also where there are - feature gaps. - -14. Proxy - -14.1 Retry SOCKS handshake on address type not supported - - When curl resolves a hostname, it might get a mix of IPv6 and IPv4 returned. - curl might then use an IPv6 address with a SOCKS5 proxy, which - if it does - not support IPv6 - returns "Address type not supported" and curl exits with - that error. - - Perhaps it is preferred if curl would in this situation instead first retry - the SOCKS handshake again for this case and then use one of the IPv4 - addresses for the target host. - - See https://github.com/curl/curl/issues/17222 - -15. Schannel - -15.1 Extend support for client certificate authentication - - The existing support for the -E/--cert and --key options could be - extended by supplying a custom certificate and key in PEM format, see: - - Getting a Certificate for Schannel - https://learn.microsoft.com/windows/win32/secauthn/getting-a-certificate-for-schannel - -15.2 Extend support for the --ciphers option - - The existing support for the --ciphers option could be extended - by mapping the OpenSSL/GnuTLS cipher suites to the Schannel APIs, see - - Specifying Schannel Ciphers and Cipher Strengths - https://learn.microsoft.com/windows/win32/secauthn/specifying-schannel-ciphers-and-cipher-strengths - -15.4 Add option to allow abrupt server closure - - libcurl with Schannel errors without a known termination point from the server - (such as length of transfer, or SSL "close notify" alert) to prevent against - a truncation attack. Really old servers may neglect to send any termination - point. An option could be added to ignore such abrupt closures. - - https://github.com/curl/curl/issues/4427 - -16. SASL - -16.1 Other authentication mechanisms - - Add support for other authentication mechanisms such as OLP, - GSS-SPNEGO and others. - -16.2 Add QOP support to GSSAPI authentication - - Currently the GSSAPI authentication only supports the default QOP of auth - (Authentication), whilst Kerberos V5 supports both auth-int (Authentication - with integrity protection) and auth-conf (Authentication with integrity and - privacy protection). - - -17. SSH protocols - -17.1 Multiplexing - - SSH is a perfectly fine multiplexed protocols which would allow libcurl to do - multiple parallel transfers from the same host using the same connection, - much in the same spirit as HTTP/2 does. libcurl however does not take - advantage of that ability but does instead always create a new connection for - new transfers even if an existing connection already exists to the host. - - To fix this, libcurl would have to detect an existing connection and "attach" - the new transfer to the existing one. - -17.2 Handle growing SFTP files - - The SFTP code in libcurl checks the file size *before* a transfer starts and - then proceeds to transfer exactly that amount of data. If the remote file - grows while the transfer is in progress libcurl does not notice and does not - adapt. The OpenSSH SFTP command line tool does and libcurl could also just - attempt to download more to see if there is more to get... - - https://github.com/curl/curl/issues/4344 - -17.3 Read keys from ~/.ssh/id_ecdsa, id_ed25519 - - The libssh2 backend in curl is limited to only reading keys from id_rsa and - id_dsa, which makes it fail connecting to servers that use more modern key - types. - - https://github.com/curl/curl/issues/8586 - -17.4 Support CURLOPT_PREQUOTE - - The two other QUOTE options are supported for SFTP, but this was left out for - unknown reasons. - -17.5 SSH over HTTPS proxy with more backends - - The SSH based protocols SFTP and SCP did not work over HTTPS proxy at - all until PR https://github.com/curl/curl/pull/6021 brought the - functionality with the libssh2 backend. Presumably, this support - can/could be added for the other backends as well. - -17.6 SFTP with SCP:// - - OpenSSH 9 switched their 'scp' tool to speak SFTP under the hood. Going - forward it might be worth having curl or libcurl attempt SFTP if SCP fails to - follow suite. - -18. Command line tool - -18.1 sync - - "curl --sync http://example.com/feed[1-100].rss" or - "curl --sync http://example.net/{index,calendar,history}.html" - - Downloads a range or set of URLs using the remote name, but only if the - remote file is newer than the local file. A Last-Modified HTTP date header - should also be used to set the mod date on the downloaded file. - -18.2 glob posts - - Globbing support for -d and -F, as in 'curl -d "name=foo[0-9]" URL'. - This is easily scripted though. - -18.4 --proxycommand - - Allow the user to make curl run a command and use its stdio to make requests - and not do any network connection by itself. Example: - - curl --proxycommand 'ssh pi@raspberrypi.local -W 10.1.1.75 80' \ - http://some/otherwise/unavailable/service.php - - See https://github.com/curl/curl/issues/4941 - -18.5 UTF-8 filenames in Content-Disposition - - RFC 6266 documents how UTF-8 names can be passed to a client in the - Content-Disposition header, and curl does not support this. - - https://github.com/curl/curl/issues/1888 - -18.6 Option to make -Z merge lined based outputs on stdout - - When a user requests multiple lined based files using -Z and sends them to - stdout, curl does not "merge" and send complete lines fine but may send - partial lines from several sources. - - https://github.com/curl/curl/issues/5175 - -18.7 specify which response codes that make -f/--fail return error - - Allows a user to better specify exactly which error code(s) that are fine - and which are errors for their specific uses cases - -18.9 Choose the name of file in braces for complex URLs - - When using braces to download a list of URLs and you use complicated names - in the list of alternatives, it could be handy to allow curl to use other - names when saving. - - Consider a way to offer that. Possibly like - {partURL1:name1,partURL2:name2,partURL3:name3} where the name following the - colon is the output name. - - See https://github.com/curl/curl/issues/221 - -18.10 improve how curl works in a Windows console window - - If you pull the scrollbar when transferring with curl in a Windows console - window, the transfer is interrupted and can get disconnected. This can - probably be improved. See https://github.com/curl/curl/issues/322 - -18.11 Windows: set attribute 'archive' for completed downloads - - The archive bit (FILE_ATTRIBUTE_ARCHIVE, 0x20) separates files that shall be - backed up from those that are either not ready or have not changed. - - Downloads in progress are neither ready to be backed up, nor should they be - opened by a different process. Only after a download has been completed it is - sensible to include it in any integer snapshot or backup of the system. - - See https://github.com/curl/curl/issues/3354 - -18.12 keep running, read instructions from pipe/socket - - Provide an option that makes curl not exit after the last URL (or even work - without a given URL), and then make it read instructions passed on a pipe or - over a socket to make further instructions so that a second subsequent curl - invoke can talk to the still running instance and ask for transfers to get - done, and thus maintain its connection pool, DNS cache and more. - -18.13 Acknowledge Ratelimit headers - - Consider a command line option that can make curl do multiple serial requests - while acknowledging server specified rate limits: - https://datatracker.ietf.org/doc/draft-ietf-httpapi-ratelimit-headers/ - - See https://github.com/curl/curl/issues/5406 - -18.14 --dry-run - - A command line option that makes curl show exactly what it would do and send - if it would run for real. - - See https://github.com/curl/curl/issues/5426 - -18.15 --retry should resume - - When --retry is used and curl actually retries transfer, it should use the - already transferred data and do a resumed transfer for the rest (when - possible) so that it does not have to transfer the same data again that was - already transferred before the retry. - - See https://github.com/curl/curl/issues/1084 - -18.17 consider filename from the redirected URL with -O ? - - When a user gives a URL and uses -O, and curl follows a redirect to a new - URL, the filename is not extracted and used from the newly redirected-to URL - even if the new URL may have a much more sensible filename. - - This is clearly documented and helps for security since there is no surprise - to users which filename that might get overwritten, but maybe a new option - could allow for this or maybe -J should imply such a treatment as well as -J - already allows for the server to decide what filename to use so it already - provides the "may overwrite any file" risk. - - This is extra tricky if the original URL has no filename part at all since - then the current code path does error out with an error message, and we - cannot *know* already at that point if curl is redirected to a URL that has a - filename... - - See https://github.com/curl/curl/issues/1241 - -18.18 retry on network is unreachable - - The --retry option retries transfers on "transient failures". We later added - --retry-connrefused to also retry for "connection refused" errors. - - Suggestions have been brought to also allow retry on "network is unreachable" - errors and while totally reasonable, maybe we should consider a way to make - this more configurable than to add a new option for every new error people - want to retry for? - - https://github.com/curl/curl/issues/1603 - -18.20 hostname sections in config files - - config files would be more powerful if they could set different - configurations depending on used URLs, hostname or possibly origin. Then a - default .curlrc could a specific user-agent only when doing requests against - a certain site. - -18.21 retry on the redirected-to URL - - When curl is told to --retry a failed transfer and follows redirects, it - might get an HTTP 429 response from the redirected-to URL and not the - original one, which then could make curl decide to rather retry the transfer - on that URL only instead of the original operation to the original URL. - - Perhaps extra emphasized if the original transfer is a large POST that - redirects to a separate GET, and that GET is what gets the 529 - - See https://github.com/curl/curl/issues/5462 - -18.23 Set the modification date on an uploaded file - - For SFTP and possibly FTP, curl could offer an option to set the - modification time for the uploaded file. - - See https://github.com/curl/curl/issues/5768 - -18.24 Use multiple parallel transfers for a single download - - To enhance transfer speed, downloading a single URL can be split up into - multiple separate range downloads that get combined into a single final - result. - - An ideal implementation would not use a specified number of parallel - transfers, but curl could: - - First start getting the full file as transfer A - - If after N seconds have passed and the transfer is expected to continue for - M seconds or more, add a new transfer (B) that asks for the second half of - A's content (and stop A at the middle). - - If splitting up the work improves the transfer rate, it could then be done - again. Then again, etc up to a limit. - - This way, if transfer B fails (because Range: is not supported) it lets - transfer A remain the single one. N and M could be set to some sensible - defaults. - - See https://github.com/curl/curl/issues/5774 - -18.25 Prevent terminal injection when writing to terminal - - curl could offer an option to make escape sequence either non-functional or - avoid cursor moves or similar to reduce the risk of a user getting tricked by - clever tricks. - - See https://github.com/curl/curl/issues/6150 - -18.26 Custom progress meter update interval - - Users who are for example doing large downloads in CI or remote setups might - want the occasional progress meter update to see that the transfer is - progressing and has not stuck, but they may not appreciate the - many-times-a-second frequency curl can end up doing it with now. - -18.27 -J and -O with %-encoded filenames - - -J/--remote-header-name does not decode %-encoded filenames. RFC 6266 details - how it should be done. The can of worm is basically that we have no charset - handling in curl and ASCII >=128 is a challenge for us. Not to mention that - decoding also means that we need to check for nastiness that is attempted, - like "../" sequences and the like. Probably everything to the left of any - embedded slashes should be cut off. - https://curl.se/bug/view.cgi?id=1294 - - -O also does not decode %-encoded names, and while it has even less - information about the charset involved the process is similar to the -J case. - - Note that we do not decode -O without the user asking for it with some other - means, since -O has always been documented to use the name exactly as - specified in the URL. - -18.28 -J with -C - - - When using -J (with -O), automatically resumed downloading together with "-C - -" fails. Without -J the same command line works. This happens because the - resume logic is worked out before the target filename (and thus its - pre-transfer size) has been figured out. This can be improved. - - https://curl.se/bug/view.cgi?id=1169 - -18.29 --retry and transfer timeouts - - If using --retry and the transfer timeouts (possibly due to using -m or - -y/-Y) the next attempt does not resume the transfer properly from what was - downloaded in the previous attempt but truncates and restarts at the original - position where it was at before the previous failed attempt. See - https://curl.se/mail/lib-2008-01/0080.html and Mandriva bug report - https://qa.mandriva.com/show_bug.cgi?id=22565 - - -19. Build - -19.2 Enable PIE and RELRO by default - - Especially when having programs that execute curl via the command line, PIE - renders the exploitation of memory corruption vulnerabilities a lot more - difficult. This can be attributed to the additional information leaks being - required to conduct a successful attack. RELRO, on the other hand, masks - different binary sections like the GOT as read-only and thus kills a handful - of techniques that come in handy when attackers are able to arbitrarily - overwrite memory. A few tests showed that enabling these features had close - to no impact, neither on the performance nor on the general functionality of - curl. - -19.3 Do not use GNU libtool on OpenBSD - - When compiling curl on OpenBSD with "--enable-debug" it gives linking errors - when you use GNU libtool. This can be fixed by using the libtool provided by - OpenBSD itself. However for this the user always needs to invoke make with - "LIBTOOL=/usr/bin/libtool". It would be nice if the script could have some - magic to detect if this system is an OpenBSD host and then use the OpenBSD - libtool instead. - - See https://github.com/curl/curl/issues/5862 - -19.4 Package curl for Windows in a signed installer - - See https://github.com/curl/curl/issues/5424 - -19.5 make configure use --cache-file more and better - - The configure script can be improved to cache more values so that repeated - invokes run much faster. - - See https://github.com/curl/curl/issues/7753 - -20. Test suite - -20.1 SSL tunnel - - Make our own version of stunnel for simple port forwarding to enable HTTPS - and FTP-SSL tests without the stunnel dependency, and it could allow us to - provide test tools built with either OpenSSL or GnuTLS - -20.2 more protocols supported - - Extend the test suite to include more protocols. The telnet could just do FTP - or http operations (for which we have test servers). - -20.3 more platforms supported - - Make the test suite work on more platforms. OpenBSD and macOS. Remove - fork()s and it should become even more portable. - -20.4 write an SMB test server to replace impacket - - This would allow us to run SMB tests on more platforms and do better and more - covering tests. - - See https://github.com/curl/curl/issues/15697 - -20.5 Use the RFC 6265 test suite - - A test suite made for HTTP cookies (RFC 6265) by Adam Barth is available at - https://github.com/abarth/http-state/tree/master/tests - - It would be good if someone would write a script/setup that would run curl - with that test suite and detect deviances. Ideally, that would even be - incorporated into our regular test suite. - -20.6 Run web-platform-tests URL tests - - Run web-platform-tests URL tests and compare results with browsers on wpt.fyi - - It would help us find issues to fix and help us document where our parser - differs from the WHATWG URL spec parsers. - - See https://github.com/curl/curl/issues/4477 - -21. MQTT - -21.1 Support rate-limiting - - The rate-limiting logic is done in the PERFORMING state in multi.c but MQTT - is not (yet) implemented to use that. - -21.2 Support MQTTS - -21.3 Handle network blocks - - Running test suite with - `CURL_DBG_SOCK_WBLOCK=90 ./runtests.pl -a mqtt` makes several - MQTT test cases fail where they should not. - -22. TFTP - -22.1 TFTP does not 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 - -23. Gopher - -23.1 Handle network blocks - - Running test suite with - `CURL_DBG_SOCK_WBLOCK=90 ./runtests.pl -a 1200 to 1300` makes several - Gopher test cases fail where they should not. diff --git a/docs/TODO.md b/docs/TODO.md new file mode 100644 index 000000000000..9d6211e6c7bc --- /dev/null +++ b/docs/TODO.md @@ -0,0 +1,1060 @@ + + +# TODO intro + +Things to do in project curl. Please tell us what you think, contribute and +send us patches that improve things. + +Be aware that these are things that we could do, or have once been considered +things we could do. If you want to work on any of these areas, please consider +bringing it up for discussions first on the mailing list so that we all agree +it is still a good idea for the project. + +All bugs documented in the [known_bugs +document](https://curl.se/docs/knownbugs.html) are subject for fixing. + +# libcurl + +## Consult `%APPDATA%` also for `.netrc` + +`%APPDATA%\.netrc` is not considered when running on Windows. Should not it? + +See [curl issue 4016](https://github.com/curl/curl/issues/4016) + +## `struct lifreq` + +Use `struct lifreq` and `SIOCGLIFADDR` instead of `struct ifreq` and +`SIOCGIFADDR` on newer Solaris versions as they claim the latter is obsolete. +To support IPv6 interface addresses for network interfaces properly. + +## alt-svc sharing + +The share interface could benefit from allowing the alt-svc cache to be +possible to share between easy handles. + +See [curl issue 4476](https://github.com/curl/curl/issues/4476) + +The share interface offers CURL_LOCK_DATA_CONNECT to have multiple easy +handle share a connection cache, but due to how connections are used they are +still not thread-safe when used shared. + +See [curl issue 4915](https://github.com/curl/curl/issues/4915) and lib1541.c + +The share interface offers CURL_LOCK_DATA_HSTS to have multiple easy handle +share an HSTS cache, but this is not thread-safe. + +## thread-safe sharing + +Using the share interface users can share some data between easy handles but +several of the sharing options are documented as not safe and supported to +share between multiple concurrent threads. Fixing this would enable more users +to share data in more powerful ways. + +## updated DNS server while running + +If `/etc/resolv.conf` gets updated while a program using libcurl is running, it +is may cause name resolves to fail unless `res_init()` is called. We should +consider calling `res_init()` + retry once unconditionally on all name resolve +failures to mitigate against this. Firefox works like that. Note that Windows +does not have `res_init()` or an alternative. + +[curl issue 2251](https://github.com/curl/curl/issues/2251) + +## c-ares and CURLOPT_OPENSOCKETFUNCTION + +curl creates most sockets via the CURLOPT_OPENSOCKETFUNCTION callback and +close them with the CURLOPT_CLOSESOCKETFUNCTION callback. However, c-ares does +not use those functions and instead opens and closes the sockets itself. This +means that when curl passes the c-ares socket to the CURLMOPT_SOCKETFUNCTION +it is not owned by the application like other sockets. + +See [curl issue 2734](https://github.com/curl/curl/issues/2734) + +## Monitor connections in the connection pool + +libcurl's connection cache or pool holds a number of open connections for the +purpose of possible subsequent connection reuse. It may contain a few up to a +significant amount of connections. Currently, libcurl leaves all connections +as they are and first when a connection is iterated over for matching or reuse +purpose it is verified that it is still alive. + +Those connections may get closed by the server side for idleness or they may +get an HTTP/2 ping from the peer to verify that they are still alive. By +adding monitoring of the connections while in the pool, libcurl can detect +dead connections (and close them) better and earlier, and it can handle HTTP/2 +pings to keep such ones alive even when not actively doing transfers on them. + +## Try to URL encode given URL + +Given a URL that for example contains spaces, libcurl could have an option +that would try somewhat harder than it does now and convert spaces to %20 and +perhaps URL encoded byte values over 128 etc (basically do what the redirect +following code already does). + +[curl issue 514](https://github.com/curl/curl/issues/514) + +## Add support for IRIs + +IRIs (RFC 3987) allow localized, non-ASCII, names in the URL. To properly +support this, curl/libcurl would need to translate/encode the given input +from the input string encoding into percent encoded output "over the wire". + +To make that work smoothly for curl users even on Windows, curl would probably +need to be able to convert from several input encodings. + +## try next proxy if one does not work + +Allow an application to specify a list of proxies to try, and failing to +connect to the first go on and try the next instead until the list is +exhausted. Browsers support this feature at least when they specify proxies +using `PAC`. + +[curl issue 896](https://github.com/curl/curl/issues/896) + +## provide timing info for each redirect + +curl and libcurl provide timing information via a set of different time-stamps +(CURLINFO_*_TIME). When curl is following redirects, those returned time value +are the accumulated sums. An improvement could be to offer separate timings +for each redirect. + +[curl issue 6743](https://github.com/curl/curl/issues/6743) + +## CURLINFO_PAUSE_STATE + +Return information about the transfer's current pause state, in both +directions. See [curl issue 2588](https://github.com/curl/curl/issues/2588) + +## Expose tried IP addresses that failed + +When libcurl fails to connect to a host, it could offer the application the +addresses that were used in the attempt. Source + destination IP, source + +destination port and protocol (UDP or TCP) for each failure. Possibly as a +callback. Perhaps also provide reason. + +[curl issue 2126](https://github.com/curl/curl/issues/2126) + +## erase secrets from heap/stack after use + +Introducing a concept and system to erase secrets from memory after use, it +could help mitigate and lessen the impact of (future) security problems etc. +However: most secrets are passed to libcurl as clear text from the application +and then clearing them within the library adds nothing... + +[curl issue 7268](https://github.com/curl/curl/issues/7268) + +## make DoH inherit more transfer properties + +Some options are not inherited because they are not relevant for the DoH SSL +connections, or inheriting the option may result in unexpected behavior. For +example the user's debug function callback is not inherited because it would +be unexpected for internal handles (i.e DoH handles) to be passed to that +callback. + +If an option is not inherited then it is not possible to set it separately +for DoH without a DoH-specific option. For example: +`CURLOPT_DOH_SSL_VERIFYHOST`, `CURLOPT_DOH_SSL_VERIFYPEER` and +`CURLOPT_DOH_SSL_VERIFYSTATUS`. + +See [curl issue 6605](https://github.com/curl/curl/issues/6605) + +# libcurl - multi interface + +## More non-blocking + +Make sure we do not ever loop because of non-blocking sockets returning +`EWOULDBLOCK` or similar. Blocking cases include: + +- Name resolves on non-Windows unless c-ares or the threaded resolver is used. +- The threaded resolver may block on cleanup: + [curl issue 4852](https://github.com/curl/curl/issues/4852) +- `file://` transfers +- TELNET transfers +- GSSAPI authentication for FTP transfers +- The "DONE" operation (post transfer protocol-specific actions) for the +protocols SFTP, SMTP, FTP. Fixing `multi_done()` for this is a worthy task. +- `curl_multi_remove_handle()` for any of the above. +- Calling `curl_ws_send()` from a callback + +## Better support for same name resolves + +If a name resolve has been initiated for a given name and a second easy handle +wants to resolve that same name as well, make it wait for the first resolve to +end up in the cache instead of doing a second separate resolve. This is +especially needed when adding many simultaneous handles using the same +hostname when the DNS resolver can get flooded. + +## Non-blocking `curl_multi_remove_handle()` + +The multi interface has a few API calls that assume a blocking behavior, like +`add_handle()` and `remove_handle()` which limits what we can do internally. +The multi API need to be moved even more into a single function that "drives" +everything in a non-blocking manner and signals when something is done. A +remove or add would then only ask for the action to get started and then +`multi_perform()` etc still be called until the add/remove is completed. + +## Split connect and authentication process + +The multi interface treats the authentication process as part of the connect +phase. As such any failures during authentication does not trigger the +relevant QUIT or LOGOFF for protocols such as IMAP, POP3 and SMTP. + +## Edge-triggered sockets should work + +The multi_socket API should work with edge-triggered socket events. One of the +internal actions that need to be improved for this to work perfectly is the +`maxloops` handling in `transfer.c:readwrite_data()`. + +## multi upkeep + +In libcurl 7.62.0 we introduced `curl_easy_upkeep`. It unfortunately only +works on easy handles. We should introduces a version of that for the multi +handle, and also consider doing `upkeep` automatically on connections in the +connection pool when the multi handle is in used. + +See [curl issue 3199](https://github.com/curl/curl/issues/3199) + +## Virtual external sockets + +libcurl performs operations on the given file descriptor that presumes it is a +socket and an application cannot replace them at the moment. Allowing an +application to fully replace those would allow a larger degree of freedom and +flexibility. + +See [curl issue 5835](https://github.com/curl/curl/issues/5835) + +## dynamically decide to use socketpair + +For users who do not use `curl_multi_wait()` or do not care for +`curl_multi_wakeup()`, we could introduce a way to make libcurl NOT create a +socketpair in the multi handle. + +See [curl issue 4829](https://github.com/curl/curl/issues/4829) + +# Documentation + +## Improve documentation about fork safety + +See [curl issue 6968](https://github.com/curl/curl/issues/6968) + +# FTP + +## A fixed directory listing format + +Since listing the contents of a remove directory with FTP is returning the +list in a format and style the server likes without any established or even +defacto standard existing, it would be a feature to users if curl could parse +the directory listing and output a general curl format that is fixed and the +same, independent of the server's choice. This would allow users to better and +more reliably extract information about remote content via FTP directory +listings. + +## GSSAPI via Windows SSPI + +In addition to currently supporting the SASL GSSAPI mechanism (Kerberos V5) +via third-party GSS-API libraries, such as MIT Kerberos, also add support for +GSSAPI authentication via Windows SSPI. + +## STAT for LIST without data connection + +Some FTP servers allow STAT for listing directories instead of using LIST, and +the response is then sent over the control connection instead of as the +otherwise used data connection. + +This is not detailed in any FTP specification. + +## Passive transfer could try other IP addresses + +When doing FTP operations through a proxy at localhost, the reported spotted +that curl only tried to connect once to the proxy, while it had multiple +addresses and a failed connect on one address should make it try the next. + +After switching to passive mode (EPSV), curl could try all IP addresses for +`localhost`. Currently it tries `::1`, but it should also try `127.0.0.1`. + +See [curl issue 1508](https://github.com/curl/curl/issues/1508) + +# HTTP + +## Provide the error body from a CONNECT response + +When curl receives a body response from a CONNECT request to a proxy, it +always just reads and ignores it. It would make some users happy if curl +instead optionally would be able to make that responsible available. Via a new +callback? Through some other means? + +See [curl issue 9513](https://github.com/curl/curl/issues/9513) + +## Obey `Retry-After` in redirects + +The `Retry-After` response header is said to dictate "the minimum time that +the user agent is asked to wait before issuing the redirected request" and +libcurl does not obey this. + +See [curl issue 11447](https://github.com/curl/curl/issues/11447) + +## Rearrange request header order + +Server implementers often make an effort to detect browser and to reject +clients it can detect to not match. One of the last details we cannot yet +control in libcurl's HTTP requests, which also can be exploited to detect that +libcurl is in fact used even when it tries to impersonate a browser, is the +order of the request headers. I propose that we introduce a new option in +which you give headers a value, and then when the HTTP request is built it +sorts the headers based on that number. We could then have internally created +headers use a default value so only headers that need to be moved have to be +specified. + +## Allow SAN names in HTTP/2 server push + +curl only allows HTTP/2 push promise if the provided :authority header value +exactly matches the hostname given in the URL. It could be extended to allow +any name that would match the Subject Alternative Names in the server's TLS +certificate. + +See [curl pull request 3581](https://github.com/curl/curl/pull/3581) + +## `auth=` in URLs + +Add the ability to specify the preferred authentication mechanism to use by +using `;auth=` in the login part of the URL. + +For example: + +`http://test:pass;auth=NTLM@example.com` would be equivalent to specifying +`--user test:pass;auth=NTLM` or `--user test:pass --ntlm` from the command +line. + +Additionally this should be implemented for proxy base URLs as well. + +## alt-svc should fallback if alt-svc does not work + +The `alt-svc:` header provides a set of alternative services for curl to use +instead of the original. If the first attempted one fails, it should try the +next etc and if all alternatives fail go back to the original. + +See [curl issue 4908](https://github.com/curl/curl/issues/4908) + +## Require HTTP version X or higher + +curl and libcurl provide options for trying higher HTTP versions (for example +HTTP/2) but then still allows the server to pick version 1.1. We could +consider adding a way to require a minimum version. + +See [curl issue 7980](https://github.com/curl/curl/issues/7980) + +# TELNET + +## ditch stdin + +Reading input (to send to the remote server) on stdin is a crappy solution for +library purposes. We need to invent a good way for the application to be able +to provide the data to send. + +## ditch telnet-specific select + +Move the telnet support's network `select()` loop go away and merge the code +into the main transfer loop. Until this is done, the multi interface does not +work for telnet. + +## feature negotiation debug data + +Add telnet feature negotiation data to the debug callback as header data. + +## exit immediately upon connection if stdin is /dev/null + +If it did, curl could be used to probe if there is an server there listening +on a specific port. That is, the following command would exit immediately +after the connection is established with exit code 0: + + curl -s --connect-timeout 2 telnet://example.com:80 NOTIFY=SUCCESS,FAILURE");`. + +[curl issue 8232](https://github.com/curl/curl/issues/8232) + +## Enhanced capability support + +Add the ability, for an application that uses libcurl, to obtain the list of +capabilities returned from the EHLO command. + +## Add `CURLOPT_MAIL_CLIENT` option + +Rather than use the URL to specify the mail client string to present in the +`HELO` and `EHLO` commands, libcurl should support a new `CURLOPT` +specifically for specifying this data as the URL is non-standard and to be +honest a bit of a hack. + +Please see the following thread for more information: +https://curl.se/mail/lib-2012-05/0178.html + +# POP3 + +## Enhanced capability support + +Add the ability, for an application that uses libcurl, to obtain the list of +capabilities returned from the CAPA command. + +# IMAP + +## Enhanced capability support + +Add the ability, for an application that uses libcurl, to obtain the list of +capabilities returned from the CAPABILITY command. + +# LDAP + +## SASL based authentication mechanisms + +Currently the LDAP module only supports `ldap_simple_bind_s()` in order to +bind to an LDAP server. However, this function sends username and password +details using the simple authentication mechanism (as clear text). However, it +should be possible to use `ldap_bind_s()` instead specifying the security +context information ourselves. + +## `CURLOPT_SSL_CTX_FUNCTION` for LDAPS + +`CURLOPT_SSL_CTX_FUNCTION` works perfectly for HTTPS and email protocols, but +it has no effect for LDAPS connections. + + [curl issue 4108](https://github.com/curl/curl/issues/4108) + +## Paged searches on LDAP server + +[curl issue 4452](https://github.com/curl/curl/issues/4452) + +## Certificate-Based Authentication + +LDAPS not possible with macOS and Windows with Certificate-Based Authentication + +[curl issue 9641](https://github.com/curl/curl/issues/9641) + +# SMB + +## Support modern versions + +curl only supports version 1, which barely anyone is using anymore. + +## File listing support + +Add support for listing the contents of an SMB share. The output should +probably be the same as/similar to FTP. + +## Honor file timestamps + +The timestamp of the transferred file should reflect that of the original +file. + +## Use NTLMv2 + +Currently the SMB authentication uses NTLMv1. + +## Create remote directories + +Support for creating remote directories when uploading a file to a directory +that does not exist on the server, just like `--ftp-create-dirs`. + +# FILE + +## Directory listing on non-POSIX + +Listing the contents of a directory accessed with FILE only works on platforms +with `opendir()`. Support could be added for more systems, like Windows. + +# TLS + +## `TLS-PSK` with OpenSSL + +Transport Layer Security pre-shared key cipher suites (`TLS-PSK`) is a set of +cryptographic protocols that provide secure communication based on pre-shared +keys (`PSK`). These pre-shared keys are symmetric keys shared in advance among +the communicating parties. + +[curl issue 5081](https://github.com/curl/curl/issues/5081) + +## TLS channel binding + +TLS 1.2 and 1.3 provide the ability to extract some secret data from the TLS +connection and use it in the client request (usually in some sort of +authentication) to ensure that the data sent is bound to the specific TLS +connection and cannot be successfully intercepted by a proxy. This +functionality can be used in a standard authentication mechanism such as +GSS-API or SCRAM, or in custom approaches like custom HTTP Authentication +headers. + +For TLS 1.2, the binding type is usually `tls-unique`, and for TLS 1.3 it is +`tls-exporter`. + +- https://datatracker.ietf.org/doc/html/rfc5929 +- https://datatracker.ietf.org/doc/html/rfc9266 +- [curl issue 9226](https://github.com/curl/curl/issues/9226) + +## Defeat TLS fingerprinting + +By changing the order of TLS extensions provided in the TLS handshake, it is +sometimes possible to circumvent TLS fingerprinting by servers. The TLS +extension order is of course not the only way to fingerprint a client. + +## Consider OCSP stapling by default + +Treat a negative response a reason for aborting the connection. Since OCSP +stapling is presumed to get used much less in the future when Let's Encrypt +drops the OCSP support, the benefit of this might however be limited. + +[curl issue 15483](https://github.com/curl/curl/issues/15483) + +## Provide callback for cert verification + +OpenSSL supports a callback for customized verification of the peer +certificate, but this does not seem to be exposed in the libcurl APIs. Could +it be? There is so much that could be done if it were. + +## Less memory massaging with Schannel + +The Schannel backend does a lot of custom memory management we would rather +avoid: the repeated allocation + free in sends and the custom memory + realloc +system for encrypted and decrypted data. That should be avoided and reduced +for 1) efficiency and 2) safety. + +## Support DANE + +[DNS-Based Authentication of Named Entities +(DANE)](https://datatracker.ietf.org/doc/html/rfc6698) is a way to provide +SSL keys and certs over DNS using DNSSEC as an alternative to the CA model. + +A patch was posted on March 7 2013 +(https://curl.se/mail/lib-2013-03/0075.html) but it was a too simple approach. +See Daniel's comments: https://curl.se/mail/lib-2013-03/0103.html + +Björn Stenberg once wrote a separate initial take on DANE that was never +completed. + +## TLS record padding + +TLS (1.3) offers optional record padding and OpenSSL provides an API for it. I +could make sense for libcurl to offer this ability to applications to make +traffic patterns harder to figure out by network traffic observers. + +See [curl issue 5398](https://github.com/curl/curl/issues/5398) + +## Support Authority Information Access certificate extension (AIA) + +AIA can provide various things like certificate revocation lists but more +importantly information about intermediate CA certificates that can allow +validation path to be fulfilled when the HTTPS server does not itself provide +them. + +Since AIA is about downloading certs on demand to complete a TLS handshake, it +is probably a bit tricky to get done right and a serious privacy leak. + +See [curl issue 2793](https://github.com/curl/curl/issues/2793) + +## 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. For more Documentation on +this see: https://curl.se/libcurl/c/tls-options.html + +[curl issue 12286](https://github.com/curl/curl/issues/12286) + +## Make sure we forbid TLS 1.3 post-handshake authentication + +RFC 8740 explains how using HTTP/2 must forbid the use of TLS 1.3 +post-handshake authentication. We should make sure to live up to that. + +See [curl issue 5396](https://github.com/curl/curl/issues/5396) + +## Support the `clienthello` extension + +Certain stupid networks and middle boxes have a problem with SSL handshake +packets that are within a certain size range because how that sets some bits +that previously (in older TLS version) were not set. The `clienthello` +extension adds padding to avoid that size range. + +- https://datatracker.ietf.org/doc/html/rfc7685 +- [curl issue 2299](https://github.com/curl/curl/issues/2299) + +## Share the CA cache + +For TLS backends that supports CA caching, it makes sense to allow the share +object to be used to store the CA cache as well via the share API. Would allow +multiple easy handles to reuse the CA cache and save themselves from a lot of +extra processing overhead. + +## Add missing features to TLS backends + +The feature matrix at https://curl.se/libcurl/c/tls-options.html shows which +features are supported by which TLS backends, and thus also where there are +feature gaps. + +# Proxy + +## Retry SOCKS handshake on address type not supported + +When curl resolves a hostname, it might get a mix of IPv6 and IPv4 returned. +curl might then use an IPv6 address with a SOCKS5 proxy, which - if it does +not support IPv6 - returns "Address type not supported" and curl exits with +that error. + +Perhaps it is preferred if curl would in this situation instead first retry +the SOCKS handshake again for this case and then use one of the IPv4 addresses +for the target host. + +See [curl issue 17222](https://github.com/curl/curl/issues/17222) + +# Schannel + +## Extend support for client certificate authentication + +The existing support for the `-E`/`--cert` and `--key` options could be +extended by supplying a custom certificate and key in PEM format, see: +[Getting a Certificate for +Schannel](https://learn.microsoft.com/windows/win32/secauthn/getting-a-certificate-for-schannel) + +## Extend support for the `--ciphers` option + +The existing support for the `--ciphers` option could be extended by mapping +the OpenSSL/GnuTLS cipher suites to the Schannel APIs, see [Specifying +Schannel Ciphers and Cipher +Strengths](https://learn.microsoft.com/windows/win32/secauthn/specifying-schannel-ciphers-and-cipher-strengths). + +## Add option to allow abrupt server closure + +libcurl with Schannel errors without a known termination point from the server +(such as length of transfer, or SSL "close notify" alert) to prevent against a +truncation attack. Really old servers may neglect to send any termination +point. An option could be added to ignore such abrupt closures. + +[curl issue 4427](https://github.com/curl/curl/issues/4427) + +# SASL + +## Other authentication mechanisms + +Add support for other authentication mechanisms such as `OLP`, `GSS-SPNEGO` +and others. + +## Add `QOP` support to GSSAPI authentication + +Currently the GSSAPI authentication only supports the default `QOP` of auth +(Authentication), whilst Kerberos V5 supports both `auth-int` (Authentication +with integrity protection) and `auth-conf` (Authentication with integrity and +privacy protection). + +# SSH protocols + +## Multiplexing + +SSH is a perfectly fine multiplexed protocols which would allow libcurl to do +multiple parallel transfers from the same host using the same connection, much +in the same spirit as HTTP/2 does. libcurl however does not take advantage of +that ability but does instead always create a new connection for new transfers +even if an existing connection already exists to the host. + +To fix this, libcurl would have to detect an existing connection and "attach" +the new transfer to the existing one. + +## Handle growing SFTP files + +The SFTP code in libcurl checks the file size *before* a transfer starts and +then proceeds to transfer exactly that amount of data. If the remote file +grows while the transfer is in progress libcurl does not notice and does not +adapt. The OpenSSH SFTP command line tool does and libcurl could also just +attempt to download more to see if there is more to get... + +[curl issue 4344](https://github.com/curl/curl/issues/4344) + +## Read keys from `~/.ssh/id_ecdsa`, `id_ed25519` + +The libssh2 backend in curl is limited to only reading keys from `id_rsa` and +`id_dsa`, which makes it fail connecting to servers that use more modern key +types. + +[curl issue 8586](https://github.com/curl/curl/issues/8586) + +## Support `CURLOPT_PREQUOTE` + +The two other `QUOTE` options are supported for SFTP, but this was left out +for unknown reasons. + +## SSH over HTTPS proxy for libssh + +The SSH based protocols SFTP and SCP did not work over HTTPS proxy at all +until [curl pull request 6021](https://github.com/curl/curl/pull/6021) brought +the functionality with the libssh2 backend. Presumably, this support can/could +be added for the libssh backend as well. + +## SFTP with `SCP://` + +OpenSSH 9 switched their `scp` tool to speak SFTP under the hood. Going +forward it might be worth having curl or libcurl attempt SFTP if SCP fails to +follow suite. + +# Command line tool + +## multi-threading + +When asked to do transfers in parallel, the curl tool could be extended to use +a number of independent worker threads. This would allow faster transfers in +situations where curl becomes CPU bound. + +Ideally, curl would (with permission) fire up new threads on demand when it +deems that it might be helpful. Perhaps, if it has more transfers to add and +the existing transfers make the CPU busy enough and there are more cores +available. + +## sync + +`curl --sync http://example.com/feed[1-100].rss` or +`curl --sync http://example.net/{index,calendar,history}.html` + +Downloads a range or set of URLs using the remote name, but only if the remote +file is newer than the local file. A `Last-Modified` HTTP date header should +also be used to set the mod date on the downloaded file. + +## glob posts + +Globbing support for `-d` and `-F`, as in `curl -d "name=foo[0-9]" URL`. This +is easily scripted though. + +## `--proxycommand` + +Allow the user to make curl run a command and use its stdio to make requests +and not do any network connection by itself. Example: + + curl --proxycommand 'ssh pi@raspberrypi.local -W 10.1.1.75 80' \ + http://some/otherwise/unavailable/service.php + +See [curl issue 4941](https://github.com/curl/curl/issues/4941) + +## UTF-8 filenames in Content-Disposition + +RFC 6266 documents how UTF-8 names can be passed to a client in the +`Content-Disposition` header, and curl does not support this. + +[curl issue 1888](https://github.com/curl/curl/issues/1888) + +## Option to make `-Z` merge lined based outputs on stdout + +When a user requests multiple lined based files using `-Z` and sends them to +stdout, curl does not *merge* and send complete lines fine but may send +partial lines from several sources. + +[curl issue 5175](https://github.com/curl/curl/issues/5175) + +## specify which response codes that make `-f`/`--fail` return error + +Allows a user to better specify exactly which error code(s) that are fine and +which are errors for their specific uses cases + +## Choose the name of file in braces for complex URLs + +When using braces to download a list of URLs and you use complicated names +in the list of alternatives, it could be handy to allow curl to use other +names when saving. + +Consider a way to offer that. Possibly like +`{partURL1:name1,partURL2:name2,partURL3:name3}` where the name following the +colon is the output name. + +See [curl issue 221](https://github.com/curl/curl/issues/221) + +## improve how curl works in a Windows console window + +If you pull the scroll bar when transferring with curl in a Windows console +window, the transfer is interrupted and can get disconnected. This can +probably be improved. See [curl issue 322](https://github.com/curl/curl/issues/322) + +## Windows: set attribute 'archive' for completed downloads + +The archive bit (`FILE_ATTRIBUTE_ARCHIVE, 0x20`) separates files that shall be +backed up from those that are either not ready or have not changed. + +Downloads in progress are neither ready to be backed up, nor should they be +opened by a different process. Only after a download has been completed it is +sensible to include it in any integer snapshot or backup of the system. + +See [curl issue 3354](https://github.com/curl/curl/issues/3354) + +## keep running, read instructions from pipe/socket + +Provide an option that makes curl not exit after the last URL (or even work +without a given URL), and then make it read instructions passed on a pipe or +over a socket to make further instructions so that a second subsequent curl +invoke can talk to the still running instance and ask for transfers to get +done, and thus maintain its connection pool, DNS cache and more. + +## Acknowledge `Ratelimit` headers + +Consider a command line option that can make curl do multiple serial requests +while acknowledging server specified [rate +limits](https://datatracker.ietf.org/doc/draft-ietf-httpapi-ratelimit-headers/). + +See [curl issue 5406](https://github.com/curl/curl/issues/5406) + +## `--dry-run` + +A command line option that makes curl show exactly what it would do and send +if it would run for real. + +See [curl issue 5426](https://github.com/curl/curl/issues/5426) + +## `--retry` should resume + +When `--retry` is used and curl actually retries transfer, it should use the +already transferred data and do a resumed transfer for the rest (when +possible) so that it does not have to transfer the same data again that was +already transferred before the retry. + +See [curl issue 1084](https://github.com/curl/curl/issues/1084) + +## consider filename from the redirected URL with `-O` ? + +When a user gives a URL and uses `-O`, and curl follows a redirect to a new +URL, the filename is not extracted and used from the newly redirected-to URL +even if the new URL may have a much more sensible filename. + +This is clearly documented and helps for security since there is no surprise +to users which filename that might get overwritten, but maybe a new option +could allow for this or maybe `-J` should imply such a treatment as well as +`-J` already allows for the server to decide what filename to use so it +already provides the "may overwrite any file" risk. + +This is extra tricky if the original URL has no filename part at all since +then the current code path does error out with an error message, and we cannot +*know* already at that point if curl is redirected to a URL that has a +filename... + +See [curl issue 1241](https://github.com/curl/curl/issues/1241) + +## retry on network is unreachable + +The `--retry` option retries transfers on *transient failures*. We later added +`--retry-connrefused` to also retry for *connection refused* errors. + +Suggestions have been brought to also allow retry on *network is unreachable* +errors and while totally reasonable, maybe we should consider a way to make +this more configurable than to add a new option for every new error people +want to retry for? + +[curl issue 1603](https://github.com/curl/curl/issues/1603) + +## hostname sections in config files + +config files would be more powerful if they could set different configurations +depending on used URLs, hostname or possibly origin. Then a default `.curlrc` +could a specific user-agent only when doing requests against a certain site. + +## retry on the redirected-to URL + +When curl is told to `--retry` a failed transfer and follows redirects, it +might get an HTTP 429 response from the redirected-to URL and not the original +one, which then could make curl decide to rather retry the transfer on that +URL only instead of the original operation to the original URL. + +Perhaps extra emphasized if the original transfer is a large POST that +redirects to a separate GET, and that GET is what gets the 529 + +See [curl issue 5462](https://github.com/curl/curl/issues/5462) + +## Set the modification date on an uploaded file + +For SFTP and possibly FTP, curl could offer an option to set the modification +time for the uploaded file. + +See [curl issue 5768](https://github.com/curl/curl/issues/5768) + +## Use multiple parallel transfers for a single download + +To enhance transfer speed, downloading a single URL can be split up into +multiple separate range downloads that get combined into a single final +result. + +An ideal implementation would not use a specified number of parallel +transfers, but curl could: +- First start getting the full file as transfer A +- If after N seconds have passed and the transfer is expected to continue for + M seconds or more, add a new transfer (B) that asks for the second half of + A's content (and stop A at the middle). +- If splitting up the work improves the transfer rate, it could then be done + again. Then again, etc up to a limit. + +This way, if transfer B fails (because Range: is not supported) it lets +transfer A remain the single one. N and M could be set to some sensible +defaults. + +See [curl issue 5774](https://github.com/curl/curl/issues/5774) + +## Prevent terminal injection when writing to terminal + +curl could offer an option to make escape sequence either non-functional or +avoid cursor moves or similar to reduce the risk of a user getting tricked by +clever tricks. + +See [curl issue 6150](https://github.com/curl/curl/issues/6150) + +## `-J` and `-O` with %-encoded filenames + +`-J`/`--remote-header-name` does not decode %-encoded filenames. RFC 6266 +details how it should be done. The can of worm is basically that we have no +charset handling in curl and ASCII >=128 is a challenge for us. Not to mention +that decoding also means that we need to check for nastiness that is +attempted, like `../` sequences and the like. Probably everything to the left +of any embedded slashes should be cut off. See +https://curl.se/bug/view.cgi?id=1294 + +`-O` also does not decode %-encoded names, and while it has even less +information about the charset involved the process is similar to the `-J` +case. + +Note that we do not decode `-O` without the user asking for it with some other +means, since `-O` has always been documented to use the name exactly as +specified in the URL. + +## `-J` with `-C -` + +When using `-J` (with `-O`), automatically resumed downloading together with +`-C -` fails. Without `-J` the same command line works. This happens because +the resume logic is worked out before the target filename (and thus its +pre-transfer size) has been figured out. This can be improved. + +https://curl.se/bug/view.cgi?id=1169 + +## `--retry` and transfer timeouts + +If using `--retry` and the transfer timeouts (possibly due to using -m or +`-y`/`-Y`) the next attempt does not resume the transfer properly from what +was downloaded in the previous attempt but truncates and restarts at the +original position where it was at before the previous failed attempt. See +https://curl.se/mail/lib-2008-01/0080.html + +# Build + +## Enable `PIE` and `RELRO` by default + +Especially when having programs that execute curl via the command line, `PIE` +renders the exploitation of memory corruption vulnerabilities a lot more +difficult. This can be attributed to the additional information leaks being +required to conduct a successful attack. `RELRO`, on the other hand, masks +different binary sections like the `GOT` as read-only and thus kills a handful +of techniques that come in handy when attackers are able to arbitrarily +overwrite memory. A few tests showed that enabling these features had close to +no impact, neither on the performance nor on the general functionality of +curl. + +## Do not use GNU libtool on OpenBSD + +When compiling curl on OpenBSD with `--enable-debug` it gives linking errors +when you use GNU libtool. This can be fixed by using the libtool provided by +OpenBSD itself. However for this the user always needs to invoke make with +`LIBTOOL=/usr/bin/libtool`. It would be nice if the script could have some +magic to detect if this system is an OpenBSD host and then use the OpenBSD +libtool instead. + +See [curl issue 5862](https://github.com/curl/curl/issues/5862) + +## Package curl for Windows in a signed installer + +See [curl issue 5424](https://github.com/curl/curl/issues/5424) + +## make configure use `--cache-file` more and better + +The configure script can be improved to cache more values so that repeated +invokes run much faster. + +See [curl issue 7753](https://github.com/curl/curl/issues/7753) + +# Test suite + +## SSL tunnel + +Make our own version of stunnel for simple port forwarding to enable HTTPS and +FTP-SSL tests without the stunnel dependency, and it could allow us to provide +test tools built with either OpenSSL or GnuTLS + +## more protocols supported + +Extend the test suite to include more protocols. The telnet could just do FTP +or http operations (for which we have test servers). + +## more platforms supported + +Make the test suite work on more platforms. OpenBSD and macOS. Remove fork()s +and it should become even more portable. + +## write an SMB test server to replace impacket + +This would allow us to run SMB tests on more platforms and do better and more +covering tests. + +See [curl issue 15697](https://github.com/curl/curl/issues/15697) + +## Use the RFC 6265 test suite + +A test suite made for HTTP cookies (RFC 6265) by Adam Barth [is +available](https://github.com/abarth/http-state/tree/master/tests). + +It would be good if someone would write a script/setup that would run curl +with that test suite and detect deviance. Ideally, that would even be +incorporated into our regular test suite. + +## Run web-platform-tests URL tests + +Run web-platform-tests URL tests and compare results with browsers on +`wpt.fyi`. + +It would help us find issues to fix and help us document where our parser +differs from the WHATWG URL spec parsers. + +See [curl issue 4477](https://github.com/curl/curl/issues/4477) + +# MQTT + +## Support rate-limiting + +The rate-limiting logic is done in the PERFORMING state in multi.c but MQTT is +not (yet) implemented to use that. + +## Support MQTTS + +## Handle network blocks + +Running test suite with `CURL_DBG_SOCK_WBLOCK=90 ./runtests.pl -a mqtt` makes +several MQTT test cases fail where they should not. + +## large payloads + +libcurl unnecessarily allocates heap memory to hold the entire payload to get +sent, when the data is already perfectly accessible where it is when +`CURLOPT_POSTFIELDS` is used. This is highly inefficient for larger payloads. +Additionally, libcurl does not support using the read callback for sending +MQTT which is yet another way to avoid having to hold large payload in memory. + +# TFTP + +## TFTP does not 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 [curl issue 12655](https://github.com/curl/curl/issues/12655) + +# Gopher + +## Handle network blocks + +Running test suite with `CURL_DBG_SOCK_WBLOCK=90 ./runtests.pl -a 1200 to +1300` makes several Gopher test cases fail where they should not. diff --git a/docs/TheArtOfHttpScripting.md b/docs/TheArtOfHttpScripting.md index 46369d6eafb0..bab52cca47b3 100644 --- a/docs/TheArtOfHttpScripting.md +++ b/docs/TheArtOfHttpScripting.md @@ -57,7 +57,7 @@ SPDX-License-Identifier: curl offer even more details as they show **everything** curl sends and receives. Use it like this: - curl --trace-ascii debugdump.txt http://www.example.com/ + curl --trace-ascii debugdump.txt https://www.example.com/ ## See the Timing @@ -67,7 +67,7 @@ SPDX-License-Identifier: curl [`--trace-time`](https://curl.se/docs/manpage.html#--trace-time) option is what you need. It prepends the time to each trace output line: - curl --trace-ascii d.txt --trace-time http://example.com/ + curl --trace-ascii d.txt --trace-time https://example.com/ ## See which Transfer @@ -78,7 +78,7 @@ SPDX-License-Identifier: curl you need. It prepends the transfer and connection identifier to each trace output line: - curl --trace-ascii d.txt --trace-ids http://example.com/ + curl --trace-ascii d.txt --trace-ids https://example.com/ ## See the Response @@ -91,7 +91,7 @@ SPDX-License-Identifier: curl 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 + https://curl.se/ or https://example.com/ a million times. RFC 3986 is the canonical spec. The formal name is not URL, it is **URI**. ## Host @@ -104,7 +104,7 @@ SPDX-License-Identifier: curl 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/ + curl --resolve www.example.org:80:127.0.0.1 https://www.example.org/ ## Port number @@ -115,14 +115,14 @@ SPDX-License-Identifier: curl number immediately following the hostname. Like when doing HTTP to port 1234: - curl http://www.example.org:1234/ + curl https://www.example.org:1234/ The port number you specify in the URL is the number that the server uses to offer its services. Sometimes you may use a proxy, and then you may need to specify that proxy's port number separately from what curl needs to connect to the server. Like when using an HTTP proxy on port 4321: - curl --proxy http://proxy.example.org:4321 http://remote.example.org/ + curl --proxy http://proxy.example.org:4321 https://remote.example.org/ ## Username and password @@ -133,11 +133,11 @@ SPDX-License-Identifier: curl You can opt to either insert the user and password in the URL or you can provide them separately: - curl http://user:password@example.org/ + curl https://user:password@example.org/ or - curl -u user:password http://example.org/ + curl -u user:password https://example.org/ You need to pay attention that this kind of HTTP authentication is not what is usually done and requested by user-oriented websites these days. They tend @@ -158,7 +158,7 @@ SPDX-License-Identifier: curl issues a GET request to the server and receives the document it asked for. If you issue the command line - curl https://curl.se + curl https://curl.se/ you get a webpage returned in your terminal window. The entire HTML document this URL identifies. @@ -188,7 +188,7 @@ SPDX-License-Identifier: curl Example, send two GET requests: - curl http://url1.example.com http://url2.example.com + curl https://url1.example.com https://url2.example.com If you use [`--data`](https://curl.se/docs/manpage.html#-d) to POST to the URL, using multiple URLs means that you send that same POST to all the @@ -196,8 +196,7 @@ SPDX-License-Identifier: curl Example, send two POSTs: - curl --data name=curl http://url1.example.com http://url2.example.com - + curl --data name=curl https://url1.example.com https://url2.example.com ## Multiple HTTP methods in a single command line @@ -214,11 +213,11 @@ SPDX-License-Identifier: curl Perhaps this is best shown with a few examples. To send first a HEAD and then a GET: - curl -I http://example.com --next http://example.com + curl -I https://example.com --next https://example.com To first send a POST and then a GET: - curl -d score=10 http://example.com/post.cgi --next http://example.com/results.html + curl -d score=10 https://example.com/post.cgi --next https://example.com/results.html # HTML forms @@ -261,7 +260,7 @@ SPDX-License-Identifier: curl To make curl do the GET form post for you, just enter the expected created URL: - curl "http://www.example.com/when/junk.cgi?birthyear=1905&press=OK" + curl "https://www.example.com/when/junk.cgi?birthyear=1905&press=OK" ## POST @@ -287,7 +286,7 @@ SPDX-License-Identifier: curl And to use curl to post this form with the same data filled in as before, we could do it like: - curl --data "birthyear=1905&press=%20OK%20" http://www.example.com/when/junk.cgi + curl --data "birthyear=1905&press=%20OK%20" https://www.example.com/when/junk.cgi This kind of POST uses the Content-Type `application/x-www-form-urlencoded` and is the most widely used POST kind. @@ -299,7 +298,7 @@ SPDX-License-Identifier: curl Recent curl versions can in fact url-encode POST data for you, like this: - curl --data-urlencode "name=I am Daniel" http://www.example.com + curl --data-urlencode "name=I am Daniel" https://www.example.com If you repeat `--data` several times on the command line, curl concatenates all the given data pieces - and put a `&` symbol between each data segment. @@ -371,7 +370,7 @@ SPDX-License-Identifier: curl Put a file to an HTTP server with curl: - curl --upload-file uploadfile http://www.example.com/receive.cgi + curl --upload-file uploadfile https://www.example.com/receive.cgi # HTTP Authentication @@ -386,7 +385,7 @@ SPDX-License-Identifier: curl To tell curl to use a user and password for authentication: - curl --user name:password http://www.example.com + curl --user name:password https://www.example.com ## Other Authentication @@ -440,7 +439,7 @@ SPDX-License-Identifier: curl Use curl to set the referer field with: - curl --referer http://www.example.come http://www.example.com + curl --referer https://www.example.come https://www.example.com ## User Agent @@ -481,7 +480,7 @@ SPDX-License-Identifier: curl To tell curl to follow a Location: - curl --location http://www.example.com + curl --location https://www.example.com If you use curl to POST to a site that immediately redirects you to another page, you can safely use [`--location`](https://curl.se/docs/manpage.html#-L) @@ -519,14 +518,14 @@ SPDX-License-Identifier: curl The simplest way to send a few cookies to the server when getting a page with curl is to add them on the command line like: - curl --cookie "name=Daniel" http://www.example.com + curl --cookie "name=Daniel" https://www.example.com Cookies are sent as common HTTP headers. This is practical as it allows curl to record cookies simply by recording headers. Record cookies with curl by using the [`--dump-header`](https://curl.se/docs/manpage.html#-D) (`-D`) option like: - curl --dump-header headers_and_cookies http://www.example.com + curl --dump-header headers_and_cookies https://www.example.com (Take note that the [`--cookie-jar`](https://curl.se/docs/manpage.html#-c) option described @@ -538,7 +537,7 @@ SPDX-License-Identifier: curl believing you had a previous connection). To use previously stored cookies, you run curl like: - curl --cookie stored_cookies_in_file http://www.example.com + curl --cookie stored_cookies_in_file https://www.example.com curl's "cookie engine" gets enabled when you use the [`--cookie`](https://curl.se/docs/manpage.html#-b) option. If you only @@ -547,7 +546,7 @@ SPDX-License-Identifier: curl page and follow a location (and thus possibly send back cookies it received), you can invoke it like: - curl --cookie nada --location http://www.example.com + curl --cookie nada --location https://www.example.com curl has the ability to read and write cookie files that use the same file format that Netscape and Mozilla once used. It is a convenient way to share @@ -557,7 +556,7 @@ SPDX-License-Identifier: curl cookie file at the end of an operation: curl --cookie cookies.txt --cookie-jar newcookies.txt \ - http://www.example.com + https://www.example.com # HTTPS @@ -620,12 +619,12 @@ SPDX-License-Identifier: curl You can delete a default header by providing one without content. Like you can ruin the request by chopping off the `Host:` header: - curl --header "Host:" http://www.example.com + curl --header "Host:" https://www.example.com You can add headers the same way. Your server may want a `Destination:` header, and you can add it: - curl --header "Destination: http://nowhere" http://example.com + curl --header "Destination: nowhere" https://example.com ## More on changed methods @@ -638,7 +637,7 @@ SPDX-License-Identifier: curl thinks 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/ + curl -X POST https://example.org/ curl however still acts as if it sent a GET so it does not send any request body etc. diff --git a/docs/URL-SYNTAX.md b/docs/URL-SYNTAX.md index 6232e3f609b8..d69ab674796d 100644 --- a/docs/URL-SYNTAX.md +++ b/docs/URL-SYNTAX.md @@ -130,7 +130,7 @@ character or string. For example, this could look like: - http://user:password@www.example.com:80/index.html?foo=bar#top + https://user:password@www.example.com:80/index.html?foo=bar#top ## Scheme @@ -169,13 +169,13 @@ local network name of the machine on your network or the IP address of the server or machine represented by either an IPv4 or IPv6 address (within brackets). For example: - http://www.example.com/ + https://www.example.com/ - http://hostname/ + https://hostname.example/ - http://192.168.0.1/ + https://192.168.0.1/ - http://[2001:1890:1112:1::20]/ + https://[2001:1890:1112:1::20]/ ### "localhost" diff --git a/docs/VERSIONS.md b/docs/VERSIONS.md index 35267f829484..b910374eab9c 100644 --- a/docs/VERSIONS.md +++ b/docs/VERSIONS.md @@ -69,7 +69,8 @@ dates. The tool was called `httpget` before 2.0, `urlget` before 4.0 then `curl` since 4.0. `libcurl` and `curl` are always released in sync, using the same version numbers. -- 8.17.0: pending +- 8.18.0: pending +- 8.17.0: November 5, 2025 - 8.16.0: September 10, 2025 - 8.15.0: July 16, 2025 - 8.14.1: June 4 2025 diff --git a/docs/cmdline-opts/CMakeLists.txt b/docs/cmdline-opts/CMakeLists.txt index 745caf047f4e..83949969aed7 100644 --- a/docs/cmdline-opts/CMakeLists.txt +++ b/docs/cmdline-opts/CMakeLists.txt @@ -40,3 +40,19 @@ add_custom_target(generate-curl.1 ALL DEPENDS "${CURL_MANPAGE}") if(NOT CURL_DISABLE_INSTALL) install(FILES "${CURL_MANPAGE}" DESTINATION "${CMAKE_INSTALL_MANDIR}/man1") endif() + +if(PERL_EXECUTABLE) + add_custom_target(curl-listhelp + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Generating src/tool_listhelp.c" VERBATIM USES_TERMINAL + COMMAND "${PERL_EXECUTABLE}" "${PROJECT_SOURCE_DIR}/scripts/managen" -d "${CMAKE_CURRENT_SOURCE_DIR}" listhelp ${DPAGES} + > "${PROJECT_SOURCE_DIR}/src/tool_listhelp.c" + DEPENDS "${PROJECT_SOURCE_DIR}/scripts/managen" ${DPAGES} + ) + add_custom_target(curl-listcats + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Generating help category constants for src/tool_help.h" VERBATIM USES_TERMINAL + COMMAND "${PERL_EXECUTABLE}" "${PROJECT_SOURCE_DIR}/scripts/managen" listcats ${DPAGES} + DEPENDS "${PROJECT_SOURCE_DIR}/scripts/managen" ${DPAGES} + ) +endif() diff --git a/docs/cmdline-opts/Makefile.am b/docs/cmdline-opts/Makefile.am index e016be286cf2..019dd57b8a56 100644 --- a/docs/cmdline-opts/Makefile.am +++ b/docs/cmdline-opts/Makefile.am @@ -40,7 +40,7 @@ GN_ = $(GN_0) MANAGEN=$(top_srcdir)/scripts/managen MAXLINE=$(top_srcdir)/scripts/maxline -# Maximum number of columns accepted in the ASCII version of the manpage +# Maximum number of columns accepted in the ASCII version of the man page INCDIR=$(top_srcdir)/include if BUILD_DOCS diff --git a/docs/cmdline-opts/_ENVIRONMENT.md b/docs/cmdline-opts/_ENVIRONMENT.md index 53fe5c34212f..1ac85fb12841 100644 --- a/docs/cmdline-opts/_ENVIRONMENT.md +++ b/docs/cmdline-opts/_ENVIRONMENT.md @@ -31,12 +31,12 @@ 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 + https://direct.example.com accesses the target URL directly, and NO_PROXY=direct.example.com curl -x http://proxy.example.com - http://somewhere.example.com + https://somewhere.example.com accesses the target URL through the proxy. diff --git a/docs/cmdline-opts/_GLOBBING.md b/docs/cmdline-opts/_GLOBBING.md index c3c7951acb27..37c8d430693d 100644 --- a/docs/cmdline-opts/_GLOBBING.md +++ b/docs/cmdline-opts/_GLOBBING.md @@ -6,7 +6,9 @@ or ranges within brackets. We call this "globbing". Provide a list with three different names like this: - http://site.{one,two,three}.com + https://fun.example/{one,two,three}.jpg + + sftp://{one,two,three}.example/README Do sequences of alphanumeric series by using [] as in: @@ -23,14 +25,14 @@ With letters through the alphabet: 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 + https://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 + https://example.com/file[1-100:10].txt - http://example.com/file[a-z:2].txt + https://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 diff --git a/docs/cmdline-opts/_PROGRESS.md b/docs/cmdline-opts/_PROGRESS.md index 9ab1ce8c9bf7..a506d041dca0 100644 --- a/docs/cmdline-opts/_PROGRESS.md +++ b/docs/cmdline-opts/_PROGRESS.md @@ -4,9 +4,10 @@ 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` for kilo, `M` for mega, `G` for giga, `T` for tera, and `P` for peta) are -1024 based. For example 1k is 1024 bytes. 1M is 1048576 bytes. +progress meter displays the transfer rate in bytes per second. The used +suffixes (`k` for kilo, `M` for mega, `G` for giga, `T` for tera, `P` for peta +and `E` for exa) are 1024 based. For example 1k is 1024 bytes. 1M is 1048576 +bytes. Strictly speaking this makes the units kibibyte and mebibyte etc. 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* @@ -14,8 +15,8 @@ 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. +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. diff --git a/docs/cmdline-opts/_WWW.md b/docs/cmdline-opts/_WWW.md index 35d946697f94..8656e9ee8c8f 100644 --- a/docs/cmdline-opts/_WWW.md +++ b/docs/cmdline-opts/_WWW.md @@ -1,4 +1,4 @@ # WWW -https://curl.se +https://curl.se/ diff --git a/docs/cmdline-opts/alt-svc.md b/docs/cmdline-opts/alt-svc.md index 257f4d5b9cb7..a3b17d04f182 100644 --- a/docs/cmdline-opts/alt-svc.md +++ b/docs/cmdline-opts/alt-svc.md @@ -24,5 +24,8 @@ filename again if it has been modified. Specify a "" filename (zero length) to avoid loading/saving and make curl just handle the cache in memory. +You may want to restrict your umask to prevent other users on the same system +to access the created file. + 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/ca-native.md b/docs/cmdline-opts/ca-native.md index a8e8c5e9a8ae..4a887df558a6 100644 --- a/docs/cmdline-opts/ca-native.md +++ b/docs/cmdline-opts/ca-native.md @@ -34,8 +34,8 @@ Fedora, RHEL), macOS, Android and iOS. (Added in 8.3.0) This option works with GnuTLS (Added in 8.5.0) and also uses Apple SecTrust when libcurl is built with it. (Added in 8.17.0) -This option works with rustls on Windows, macOS, Android and iOS. On Linux it -is equivalent to using the Mozilla CA certificate bundle. When used with rustls +This option works with Rustls on Windows, macOS, Android and iOS. On Linux it +is equivalent to using the Mozilla CA certificate bundle. When used with Rustls _only_ the native CA store is consulted, not other locations set at run time or build time. (Added in 8.13.0) diff --git a/docs/cmdline-opts/compressed.md b/docs/cmdline-opts/compressed.md index 35bbab813960..a66cdff4fd86 100644 --- a/docs/cmdline-opts/compressed.md +++ b/docs/cmdline-opts/compressed.md @@ -25,3 +25,6 @@ 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. + +**WARNING**: when decompressing data, even tiny transfers might be expanded +and generate a huge amount of bytes. diff --git a/docs/cmdline-opts/cookie-jar.md b/docs/cmdline-opts/cookie-jar.md index 103144acc314..de09fd5274d4 100644 --- a/docs/cmdline-opts/cookie-jar.md +++ b/docs/cmdline-opts/cookie-jar.md @@ -37,3 +37,6 @@ 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. + +You may want to restrict your umask to prevent other users on the same system +to access the created file. diff --git a/docs/cmdline-opts/form.md b/docs/cmdline-opts/form.md index 100e29e5716e..abe4fa998b25 100644 --- a/docs/cmdline-opts/form.md +++ b/docs/cmdline-opts/form.md @@ -127,7 +127,7 @@ text file: curl -F '=(;type=multipart/alternative' \ -F '=plain text message' \ -F '= HTML message;type=text/html' \ - -F '=)' -F '=@textfile.txt' ... smtp://example.com + -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 diff --git a/docs/cmdline-opts/header.md b/docs/cmdline-opts/header.md index 66816aac538b..7af86aba1833 100644 --- a/docs/cmdline-opts/header.md +++ b/docs/cmdline-opts/header.md @@ -12,6 +12,7 @@ Multi: append See-also: - user-agent - referer + - proxy-header Example: - -H "X-First-Name: Joe" $URL - -H "User-Agent: yes-please/2000" $URL diff --git a/docs/cmdline-opts/hsts.md b/docs/cmdline-opts/hsts.md index ca6b07e66d66..f58566e95dfb 100644 --- a/docs/cmdline-opts/hsts.md +++ b/docs/cmdline-opts/hsts.md @@ -28,5 +28,8 @@ performed. Specify a "" filename (zero length) to avoid loading/saving and make curl just handle HSTS in memory. +You may want to restrict your umask to prevent other users on the same system +to access the created file. + 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/limit-rate.md b/docs/cmdline-opts/limit-rate.md index c5e276e1b575..f58fd1fcd865 100644 --- a/docs/cmdline-opts/limit-rate.md +++ b/docs/cmdline-opts/limit-rate.md @@ -15,6 +15,7 @@ Example: - --limit-rate 100K $URL - --limit-rate 1000 $URL - --limit-rate 10M $URL + - --limit-rate 200K --max-time 60 $URL --- # `--limit-rate` diff --git a/docs/cmdline-opts/list-only.md b/docs/cmdline-opts/list-only.md index 2800a8f79313..eb52d8884972 100644 --- a/docs/cmdline-opts/list-only.md +++ b/docs/cmdline-opts/list-only.md @@ -24,7 +24,7 @@ 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. +include subdirectories and symbolic links. 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 diff --git a/docs/cmdline-opts/proxy-cacert.md b/docs/cmdline-opts/proxy-cacert.md index 682349a7e260..0b2405d1c96a 100644 --- a/docs/cmdline-opts/proxy-cacert.md +++ b/docs/cmdline-opts/proxy-cacert.md @@ -14,7 +14,7 @@ See-also: - dump-ca-embed - proxy Example: - - --proxy-cacert CA-file.txt -x https://proxy $URL + - --proxy-cacert CA-file.txt -x https://proxy.example $URL --- # `--proxy-cacert` diff --git a/docs/cmdline-opts/proxy-capath.md b/docs/cmdline-opts/proxy-capath.md index 91575ae4d8b8..344756a43ebb 100644 --- a/docs/cmdline-opts/proxy-capath.md +++ b/docs/cmdline-opts/proxy-capath.md @@ -13,7 +13,7 @@ See-also: - capath - dump-ca-embed Example: - - --proxy-capath /local/directory -x https://proxy $URL + - --proxy-capath /local/directory -x https://proxy.example $URL --- # `--proxy-capath` diff --git a/docs/cmdline-opts/proxy-cert-type.md b/docs/cmdline-opts/proxy-cert-type.md index 8a1121bb36b3..3dcd2017c46e 100644 --- a/docs/cmdline-opts/proxy-cert-type.md +++ b/docs/cmdline-opts/proxy-cert-type.md @@ -11,7 +11,7 @@ See-also: - proxy-cert - proxy-key Example: - - --proxy-cert-type PEM --proxy-cert file -x https://proxy $URL + - --proxy-cert-type PEM --proxy-cert file -x https://proxy.example $URL --- # `--proxy-cert-type` diff --git a/docs/cmdline-opts/proxy-cert.md b/docs/cmdline-opts/proxy-cert.md index 734766730c67..929791e3a152 100644 --- a/docs/cmdline-opts/proxy-cert.md +++ b/docs/cmdline-opts/proxy-cert.md @@ -12,7 +12,7 @@ See-also: - proxy-key - proxy-cert-type Example: - - --proxy-cert file -x https://proxy $URL + - --proxy-cert file -x https://proxy.example $URL --- # `--proxy-cert` diff --git a/docs/cmdline-opts/proxy-ciphers.md b/docs/cmdline-opts/proxy-ciphers.md index 420e7563bdd7..4cb85e1e67fa 100644 --- a/docs/cmdline-opts/proxy-ciphers.md +++ b/docs/cmdline-opts/proxy-ciphers.md @@ -13,7 +13,7 @@ See-also: - ciphers - proxy Example: - - --proxy-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256 -x https://proxy $URL + - --proxy-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256 -x https://proxy.example $URL --- # `--proxy-ciphers` diff --git a/docs/cmdline-opts/proxy-crlfile.md b/docs/cmdline-opts/proxy-crlfile.md index 726e44955781..9f7d3304fa2b 100644 --- a/docs/cmdline-opts/proxy-crlfile.md +++ b/docs/cmdline-opts/proxy-crlfile.md @@ -11,7 +11,7 @@ See-also: - crlfile - proxy Example: - - --proxy-crlfile rejects.txt -x https://proxy $URL + - --proxy-crlfile rejects.txt -x https://proxy.example $URL --- # `--proxy-crlfile` diff --git a/docs/cmdline-opts/proxy-header.md b/docs/cmdline-opts/proxy-header.md index 3edf6c9a90e5..459eb462f683 100644 --- a/docs/cmdline-opts/proxy-header.md +++ b/docs/cmdline-opts/proxy-header.md @@ -10,6 +10,7 @@ Category: proxy Multi: append See-also: - proxy + - header Example: - --proxy-header "X-First-Name: Joe" -x http://proxy $URL - --proxy-header "User-Agent: surprise" -x http://proxy $URL diff --git a/docs/cmdline-opts/proxy-insecure.md b/docs/cmdline-opts/proxy-insecure.md index 5796c36237d5..0c2d8b99bc08 100644 --- a/docs/cmdline-opts/proxy-insecure.md +++ b/docs/cmdline-opts/proxy-insecure.md @@ -10,7 +10,7 @@ See-also: - proxy - insecure Example: - - --proxy-insecure -x https://proxy $URL + - --proxy-insecure -x https://proxy.example $URL --- # `--proxy-insecure` diff --git a/docs/cmdline-opts/proxy-key-type.md b/docs/cmdline-opts/proxy-key-type.md index 587c13c59284..e4551400168d 100644 --- a/docs/cmdline-opts/proxy-key-type.md +++ b/docs/cmdline-opts/proxy-key-type.md @@ -11,7 +11,7 @@ See-also: - proxy-key - proxy Example: - - --proxy-key-type DER --proxy-key here -x https://proxy $URL + - --proxy-key-type DER --proxy-key here -x https://proxy.example $URL --- # `--proxy-key-type` diff --git a/docs/cmdline-opts/proxy-key.md b/docs/cmdline-opts/proxy-key.md index 7caa636e363f..8ee78c46eac6 100644 --- a/docs/cmdline-opts/proxy-key.md +++ b/docs/cmdline-opts/proxy-key.md @@ -11,7 +11,7 @@ See-also: - proxy-key-type - proxy Example: - - --proxy-key here -x https://proxy $URL + - --proxy-key here -x https://proxy.example $URL --- # `--proxy-key` diff --git a/docs/cmdline-opts/proxy-pass.md b/docs/cmdline-opts/proxy-pass.md index 88cefd54c894..1005d95d2f3a 100644 --- a/docs/cmdline-opts/proxy-pass.md +++ b/docs/cmdline-opts/proxy-pass.md @@ -11,7 +11,7 @@ See-also: - proxy - proxy-key Example: - - --proxy-pass secret --proxy-key here -x https://proxy $URL + - --proxy-pass secret --proxy-key here -x https://proxy.example $URL --- # `--proxy-pass` diff --git a/docs/cmdline-opts/proxy-ssl-allow-beast.md b/docs/cmdline-opts/proxy-ssl-allow-beast.md index 089038dec49d..909a7f026ed1 100644 --- a/docs/cmdline-opts/proxy-ssl-allow-beast.md +++ b/docs/cmdline-opts/proxy-ssl-allow-beast.md @@ -10,7 +10,7 @@ See-also: - ssl-allow-beast - proxy Example: - - --proxy-ssl-allow-beast -x https://proxy $URL + - --proxy-ssl-allow-beast -x https://proxy.example $URL --- # `--proxy-ssl-allow-beast` diff --git a/docs/cmdline-opts/proxy-ssl-auto-client-cert.md b/docs/cmdline-opts/proxy-ssl-auto-client-cert.md index 578a7a6417cd..e041b81523a2 100644 --- a/docs/cmdline-opts/proxy-ssl-auto-client-cert.md +++ b/docs/cmdline-opts/proxy-ssl-auto-client-cert.md @@ -10,7 +10,7 @@ See-also: - ssl-auto-client-cert - proxy Example: - - --proxy-ssl-auto-client-cert -x https://proxy $URL + - --proxy-ssl-auto-client-cert -x https://proxy.example $URL --- # `--proxy-ssl-auto-client-cert` diff --git a/docs/cmdline-opts/proxy-tlsauthtype.md b/docs/cmdline-opts/proxy-tlsauthtype.md index 684a7d55ef06..84becc149e99 100644 --- a/docs/cmdline-opts/proxy-tlsauthtype.md +++ b/docs/cmdline-opts/proxy-tlsauthtype.md @@ -12,7 +12,7 @@ See-also: - proxy-tlsuser - proxy-tlspassword Example: - - --proxy-tlsauthtype SRP -x https://proxy $URL + - --proxy-tlsauthtype SRP -x https://proxy.example $URL --- # `--proxy-tlsauthtype` diff --git a/docs/cmdline-opts/proxy-tlspassword.md b/docs/cmdline-opts/proxy-tlspassword.md index fe9ae7d2e200..63c252156627 100644 --- a/docs/cmdline-opts/proxy-tlspassword.md +++ b/docs/cmdline-opts/proxy-tlspassword.md @@ -11,7 +11,7 @@ See-also: - proxy - proxy-tlsuser Example: - - --proxy-tlspassword passwd -x https://proxy $URL + - --proxy-tlspassword passwd -x https://proxy.example $URL --- # `--proxy-tlspassword` diff --git a/docs/cmdline-opts/proxy-tlsuser.md b/docs/cmdline-opts/proxy-tlsuser.md index 351770111948..610a2169b885 100644 --- a/docs/cmdline-opts/proxy-tlsuser.md +++ b/docs/cmdline-opts/proxy-tlsuser.md @@ -11,7 +11,7 @@ See-also: - proxy - proxy-tlspassword Example: - - --proxy-tlsuser smith -x https://proxy $URL + - --proxy-tlsuser smith -x https://proxy.example $URL --- # `--proxy-tlsuser` diff --git a/docs/cmdline-opts/proxy-tlsv1.md b/docs/cmdline-opts/proxy-tlsv1.md index 7b322e3a32de..20643fd82b80 100644 --- a/docs/cmdline-opts/proxy-tlsv1.md +++ b/docs/cmdline-opts/proxy-tlsv1.md @@ -9,7 +9,7 @@ Multi: mutex See-also: - proxy Example: - - --proxy-tlsv1 -x https://proxy $URL + - --proxy-tlsv1 -x https://proxy.example $URL --- # `--proxy-tlsv1` diff --git a/docs/cmdline-opts/socks4.md b/docs/cmdline-opts/socks4.md index 8e92d5930cb3..59ec172b8d86 100644 --- a/docs/cmdline-opts/socks4.md +++ b/docs/cmdline-opts/socks4.md @@ -7,6 +7,7 @@ Help: SOCKS4 proxy on given host + port Added: 7.15.2 Category: proxy Multi: single +Mutexed: proxy socks4a socks5 socks5-hostname See-also: - socks4a - socks5 @@ -21,8 +22,9 @@ Use the specified SOCKS4 proxy. If the port number is not specified, it is assumed at port 1080. Using this socket type makes curl resolve the hostname and pass 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` +To specify the proxy on a Unix domain socket, use localhost for host and +append the absolute path to the domain socket. For example: +`socks4://localhost/path/to/socket.sock` (the scheme may be omitted). This option overrides any previous use of --proxy, as they are mutually exclusive. diff --git a/docs/cmdline-opts/socks4a.md b/docs/cmdline-opts/socks4a.md index 04d60b81b66d..9e451cf7b063 100644 --- a/docs/cmdline-opts/socks4a.md +++ b/docs/cmdline-opts/socks4a.md @@ -7,6 +7,7 @@ Help: SOCKS4a proxy on given host + port Added: 7.18.0 Category: proxy Multi: single +Mutexed: proxy socks4 socks5 socks5-hostname See-also: - socks4 - socks5 @@ -20,8 +21,9 @@ Example: 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 hostname. -To specify proxy on a Unix domain socket, use localhost for host, e.g. -`socks4a://localhost/path/to/socket.sock` +To specify the proxy on a Unix domain socket, use localhost for host and +append the absolute path to the domain socket. For example: +`socks4a://localhost/path/to/socket.sock` (the scheme may be omitted). This option overrides any previous use of --proxy, as they are mutually exclusive. diff --git a/docs/cmdline-opts/socks5-hostname.md b/docs/cmdline-opts/socks5-hostname.md index 0ea2ed739fb9..b558248a78b9 100644 --- a/docs/cmdline-opts/socks5-hostname.md +++ b/docs/cmdline-opts/socks5-hostname.md @@ -7,6 +7,7 @@ Help: SOCKS5 proxy, pass hostname to proxy Added: 7.18.0 Category: proxy Multi: single +Mutexed: proxy socks4 socks4a socks5 See-also: - socks5 - socks4a @@ -19,8 +20,9 @@ Example: Use the specified SOCKS5 proxy (and let the proxy resolve the hostname). 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` +To specify the proxy on a Unix domain socket, use localhost for host and +append the absolute path to the domain socket. For example: +`socks5h://localhost/path/to/socket.sock` (the scheme may be omitted). This option overrides any previous use of --proxy, as they are mutually exclusive. diff --git a/docs/cmdline-opts/socks5.md b/docs/cmdline-opts/socks5.md index 4ea660d62d47..3aa65b33adda 100644 --- a/docs/cmdline-opts/socks5.md +++ b/docs/cmdline-opts/socks5.md @@ -10,8 +10,10 @@ Multi: single See-also: - socks5-hostname - socks4a +Mutexed: proxy socks4 socks4a socks5-hostname Example: - --socks5 proxy.example:7000 $URL + - --socks5 localhost/path/unix-domain $URL --- # `--socks5` @@ -19,8 +21,9 @@ Example: Use the specified SOCKS5 proxy - but resolve the hostname 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` +To specify the proxy on a Unix domain socket, use localhost for host and +append the absolute path to the domain socket. For example: +`socks5://localhost/path/to/socket.sock` (the scheme may be omitted). This option overrides any previous use of --proxy, as they are mutually exclusive. diff --git a/docs/cmdline-opts/ssl.md b/docs/cmdline-opts/ssl.md index 0c0f28172acb..5951d0199123 100644 --- a/docs/cmdline-opts/ssl.md +++ b/docs/cmdline-opts/ssl.md @@ -28,8 +28,7 @@ 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. +Please note that a server may close the connection if the negotiation fails. 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/tls-earlydata.md b/docs/cmdline-opts/tls-earlydata.md index 642897798304..8e344758be5e 100644 --- a/docs/cmdline-opts/tls-earlydata.md +++ b/docs/cmdline-opts/tls-earlydata.md @@ -21,7 +21,7 @@ Enable the use of TLSv1.3 early data, also known as '0RTT' where possible. This has security implications for the requests sent that way. This option can be used when curl is built to use GnuTLS, wolfSSL, quictls and -OpenSSL as a TLS provider (but not BoringSSL, AWS-LC, or rustls). +OpenSSL as a TLS provider (but not BoringSSL, AWS-LC, or Rustls). If a server supports this TLSv1.3 feature, and to what extent, is announced as part of the TLS "session" sent back to curl. Until curl has seen such diff --git a/docs/cmdline-opts/upload-flags.md b/docs/cmdline-opts/upload-flags.md index d17614876836..6c014d0895f3 100644 --- a/docs/cmdline-opts/upload-flags.md +++ b/docs/cmdline-opts/upload-flags.md @@ -21,5 +21,5 @@ specified as either a single flag value or a comma-separated list of flag values. These values are case-sensitive and may be negated by prepending them with a '-' character. Currently the following flag values are accepted: answered, deleted, draft, flagged, and -seen. The currently-accepted flag values are used to set flags on +seen. The currently accepted flag values are used to set flags on IMAP uploads. diff --git a/docs/cmdline-opts/write-out.md b/docs/cmdline-opts/write-out.md index 9946349c1552..5b8fdb3e47ee 100644 --- a/docs/cmdline-opts/write-out.md +++ b/docs/cmdline-opts/write-out.md @@ -245,8 +245,8 @@ The time, in seconds, it took from the start until the name resolving was completed. ## `time_posttransfer` -The time it took from the start until the last byte is sent by libcurl. -In microseconds. (Added in 8.10.0) +The time, in seconds, it took from the start until the last byte is sent +by libcurl. (Added in 8.10.0) ## `time_pretransfer` The time, in seconds, it took from the start until the file transfer was just diff --git a/docs/examples/.checksrc b/docs/examples/.checksrc index e35dccc7261d..8c7b0c901e80 100644 --- a/docs/examples/.checksrc +++ b/docs/examples/.checksrc @@ -2,17 +2,24 @@ # # SPDX-License-Identifier: curl +allowfunc atoi +allowfunc atol +allowfunc calloc allowfunc fclose allowfunc fdopen allowfunc fopen allowfunc fprintf +allowfunc free allowfunc gmtime allowfunc localtime +allowfunc malloc allowfunc open allowfunc printf +allowfunc realloc allowfunc snprintf allowfunc socket allowfunc sscanf +allowfunc strdup allowfunc strerror allowfunc vsnprintf diff --git a/docs/examples/.gitignore b/docs/examples/.gitignore index 788eefe1ef17..c96ad9127201 100644 --- a/docs/examples/.gitignore +++ b/docs/examples/.gitignore @@ -79,7 +79,6 @@ multi-legacy multi-post multi-single multi-uv -multithread netrc parseurl persistent @@ -123,7 +122,7 @@ smtp-tls smtp-vrfy sslbackend synctime -threaded-ssl +threaded unixsocket url2file urlapi diff --git a/docs/examples/10-at-a-time.c b/docs/examples/10-at-a-time.c index 87971cbde62f..e5cd1f1ad91e 100644 --- a/docs/examples/10-at-a-time.c +++ b/docs/examples/10-at-a-time.c @@ -25,132 +25,133 @@ * Download many files in parallel, in the same thread. * */ - #include #include + #include static const char *urls[] = { - "https://www.microsoft.com", - "https://opensource.org", - "https://www.google.com", - "https://www.yahoo.com", - "https://www.ibm.com", - "https://www.mysql.com", - "https://www.oracle.com", - "https://www.ripe.net", - "https://www.iana.org", - "https://www.amazon.com", - "https://www.netcraft.com", - "https://www.heise.de", - "https://www.chip.de", - "https://www.ca.com", - "https://www.cnet.com", - "https://www.mozilla.org", - "https://www.cnn.com", - "https://www.wikipedia.org", - "https://www.dell.com", - "https://www.hp.com", - "https://www.cert.org", - "https://www.mit.edu", - "https://www.nist.gov", - "https://www.ebay.com", - "https://www.playstation.com", - "https://www.uefa.com", - "https://www.ieee.org", - "https://www.apple.com", - "https://www.symantec.com", - "https://www.zdnet.com", - "https://www.fujitsu.com/global/", - "https://www.supermicro.com", - "https://www.hotmail.com", - "https://www.ietf.org", - "https://www.bbc.co.uk", - "https://news.google.com", - "https://www.foxnews.com", - "https://www.msn.com", - "https://www.wired.com", - "https://www.sky.com", - "https://www.usatoday.com", - "https://www.cbs.com", - "https://www.nbc.com/", - "https://slashdot.org", - "https://www.informationweek.com", - "https://apache.org", - "https://www.un.org", + "https://01.example/", + "https://02.example/", + "https://03.example/", + "https://04.example/", + "https://05.example/", + "https://06.example/", + "https://07.example/", + "https://08.example/", + "https://09.example/", + "https://10.example/", + "https://11.example/", + "https://12.example/", + "https://13.example/", + "https://14.example/", + "https://15.example/", + "https://16.example/", + "https://17.example/", + "https://18.example/", + "https://19.example/", + "https://20.example/", + "https://21.example/", + "https://22.example/", + "https://23.example/", + "https://24.example/", + "https://25.example/", + "https://26.example/", + "https://27.example/", + "https://28.example/", + "https://29.example/", + "https://30.example/", + "https://31.example/", + "https://32.example/", + "https://33.example/", + "https://34.example/", + "https://35.example/", + "https://36.example/", + "https://37.example/", + "https://38.example/", + "https://39.example/", + "https://40.example/", + "https://41.example/", + "https://42.example/", + "https://43.example/", + "https://44.example/", + "https://45.example/", + "https://46.example/", }; -#define MAX_PARALLEL 10 /* number of simultaneous transfers */ -#define NUM_URLS sizeof(urls)/sizeof(char *) +#define MAX_PARALLEL 10 /* number of simultaneous transfers */ +#define NUM_URLS (sizeof(urls) / sizeof(char *)) static size_t write_cb(char *data, size_t n, size_t l, void *userp) { /* take care of the data here, ignored in this example */ (void)data; (void)userp; - return n*l; + return n * l; } -static void add_transfer(CURLM *cm, unsigned int i, int *left) +static void add_transfer(CURLM *multi, unsigned int i, int *left) { - CURL *eh = curl_easy_init(); - curl_easy_setopt(eh, CURLOPT_WRITEFUNCTION, write_cb); - curl_easy_setopt(eh, CURLOPT_URL, urls[i]); - curl_easy_setopt(eh, CURLOPT_PRIVATE, urls[i]); - curl_multi_add_handle(cm, eh); + CURL *curl = curl_easy_init(); + if(curl) { + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); + curl_easy_setopt(curl, CURLOPT_URL, urls[i]); + curl_easy_setopt(curl, CURLOPT_PRIVATE, urls[i]); + curl_multi_add_handle(multi, curl); + } (*left)++; } int main(void) { - CURLM *cm; + CURLM *multi; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; - cm = curl_multi_init(); - if(cm) { + multi = curl_multi_init(); + if(multi) { CURLMsg *msg; unsigned int transfers = 0; int msgs_left = -1; int left = 0; /* Limit the amount of simultaneous connections curl should allow: */ - curl_multi_setopt(cm, CURLMOPT_MAXCONNECTS, (long)MAX_PARALLEL); + curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, (long)MAX_PARALLEL); for(transfers = 0; transfers < MAX_PARALLEL && transfers < NUM_URLS; transfers++) - add_transfer(cm, transfers, &left); + add_transfer(multi, transfers, &left); do { int still_alive = 1; - curl_multi_perform(cm, &still_alive); + curl_multi_perform(multi, &still_alive); /* !checksrc! disable EQUALSNULL 1 */ - while((msg = curl_multi_info_read(cm, &msgs_left)) != NULL) { + while((msg = curl_multi_info_read(multi, &msgs_left)) != NULL) { if(msg->msg == CURLMSG_DONE) { char *url; - CURL *e = msg->easy_handle; - curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &url); + CURL *curl = msg->easy_handle; + curl_easy_getinfo(curl, CURLINFO_PRIVATE, &url); fprintf(stderr, "R: %d - %s <%s>\n", msg->data.result, curl_easy_strerror(msg->data.result), url); - curl_multi_remove_handle(cm, e); - curl_easy_cleanup(e); + curl_multi_remove_handle(multi, curl); + curl_easy_cleanup(curl); left--; } else { fprintf(stderr, "E: CURLMsg (%d)\n", msg->msg); } if(transfers < NUM_URLS) - add_transfer(cm, transfers++, &left); + add_transfer(multi, transfers++, &left); } if(left) - curl_multi_wait(cm, NULL, 0, 1000, NULL); + curl_multi_wait(multi, NULL, 0, 1000, NULL); } while(left); - curl_multi_cleanup(cm); + curl_multi_cleanup(multi); } curl_global_cleanup(); diff --git a/docs/examples/CMakeLists.txt b/docs/examples/CMakeLists.txt index c86e8439fda7..31f280898123 100644 --- a/docs/examples/CMakeLists.txt +++ b/docs/examples/CMakeLists.txt @@ -83,8 +83,7 @@ foreach(_target IN LISTS COMPLICATED_MAY_BUILD check_PROGRAMS _all) # keep 'COM add_dependencies(curl-examples ${_target_name}) endif() target_link_libraries(${_target_name} ${LIB_SELECTED} ${CURL_NETWORK_AND_TIME_LIBS} ${_more_libs}) - target_compile_definitions(${_target_name} PRIVATE "CURL_NO_OLDIES" - "$<$:WIN32_LEAN_AND_MEAN>" "$<$:_CRT_SECURE_NO_DEPRECATE>") + target_compile_definitions(${_target_name} PRIVATE "CURL_NO_OLDIES" "$<$:WIN32_LEAN_AND_MEAN>") set_target_properties(${_target_name} PROPERTIES OUTPUT_NAME "${_target}" PROJECT_LABEL "Example ${_target}" UNITY_BUILD OFF) endforeach() diff --git a/docs/examples/Makefile.example b/docs/examples/Makefile.example index fbbca8a9a9c0..4031aa2e4366 100644 --- a/docs/examples/Makefile.example +++ b/docs/examples/Makefile.example @@ -22,7 +22,7 @@ # ########################################################################### -SRC ?= ftpget.c +SRC ?= https.c # What to call the final executable TARGET ?= example @@ -36,12 +36,12 @@ CFLAGS ?= -g # This should point to a directory that holds libcurl, if it is not in the # system's standard lib dir # We also set a -L to include the directory where we have the OpenSSL libraries -LDFLAGS ?= -L/home/dast/lib -L/usr/local/ssl/lib +LDFLAGS ?= -L/usr/lib -L/usr/local/lib # We need -lsocket and -lnsl when on Solaris # We need -lssl and -lcrypto when using libcurl with TLS support # We need -lpthread for the pthread example -LIBS ?= -lsocket -lnsl -lssl -lcrypto +LIBS ?= -lssl -lcrypto # We need -lcurl for the curl stuff LIBS := -lcurl $(LIBS) diff --git a/docs/examples/Makefile.inc b/docs/examples/Makefile.inc index 29c4e3e997bd..8c85fb838232 100644 --- a/docs/examples/Makefile.inc +++ b/docs/examples/Makefile.inc @@ -146,9 +146,8 @@ check_PROGRAMS = \ COMPLICATED_MAY_BUILD = \ cacertinmem.c \ multi-uv.c \ - multithread.c \ sessioninfo.c \ - threaded-ssl.c \ + threaded.c \ usercertinmem.c # These examples require external dependencies that may not be commonly diff --git a/docs/examples/address-scope.c b/docs/examples/address-scope.c index 82607e2df50e..dba6c8f77333 100644 --- a/docs/examples/address-scope.c +++ b/docs/examples/address-scope.c @@ -26,6 +26,7 @@ * */ #include + #include #if !defined(_WIN32) && !defined(MSDOS) && !defined(__AMIGA__) @@ -38,9 +39,9 @@ int main(void) /* Windows/MS-DOS users need to find how to use if_nametoindex() */ CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -50,18 +51,18 @@ int main(void) my_scope_id = (long)if_nametoindex("eth0"); curl_easy_setopt(curl, CURLOPT_ADDRESS_SCOPE, my_scope_id); - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); } curl_global_cleanup(); - return (int)res; + return (int)result; #else return 0; #endif diff --git a/docs/examples/altsvc.c b/docs/examples/altsvc.c index 4021c90002e9..bb813aa3f7af 100644 --- a/docs/examples/altsvc.c +++ b/docs/examples/altsvc.c @@ -26,15 +26,16 @@ * */ #include + #include int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -47,16 +48,16 @@ int main(void) curl_easy_setopt(curl, CURLOPT_ALTSVC_CTRL, CURLALTSVC_H1 | CURLALTSVC_H2 | CURLALTSVC_H3); - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/anyauthput.c b/docs/examples/anyauthput.c index 8718ac98bbed..cdc0ad9e5f87 100644 --- a/docs/examples/anyauthput.c +++ b/docs/examples/anyauthput.c @@ -26,6 +26,12 @@ * one the server supports/wants. * */ +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* for fopen() */ +#endif +#endif + #include #include #include @@ -35,9 +41,9 @@ #ifdef _WIN32 #undef stat -#define stat _stat +#define stat _stati64 #undef fstat -#define fstat _fstat +#define fstat _fstati64 #define fileno _fileno #endif @@ -59,9 +65,9 @@ /* seek callback function */ static int my_seek(void *userp, curl_off_t offset, int origin) { - FILE *fp = (FILE *) userp; + FILE *fp = (FILE *)userp; - if(fseek(fp, (long) offset, origin) == -1) + if(fseek(fp, (long)offset, origin) == -1) /* could not seek */ return CURL_SEEKFUNC_CANTSEEK; @@ -69,7 +75,7 @@ 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) +static size_t read_cb(char *ptr, size_t size, size_t nmemb, void *stream) { size_t nread; @@ -85,7 +91,7 @@ static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream) int main(int argc, char **argv) { CURL *curl; - CURLcode res; + CURLcode result; FILE *fp; struct stat file_info; @@ -103,37 +109,32 @@ int main(int argc, char **argv) if(!fp) return 2; -#ifdef UNDER_CE - /* !checksrc! disable BANNEDFUNC 1 */ - if(stat(file, &file_info) != 0) { -#else if(fstat(fileno(fp), &file_info) != 0) { -#endif fclose(fp); return 1; /* cannot continue */ } /* In Windows, this inits the Winsock stuff */ - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) { + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) { fclose(fp); - return (int)res; + return (int)result; } /* get a curl handle */ curl = curl_easy_init(); if(curl) { /* we want to use our own read function */ - curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback); + curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_cb); /* which file to upload */ - curl_easy_setopt(curl, CURLOPT_READDATA, (void *) fp); + curl_easy_setopt(curl, CURLOPT_READDATA, (void *)fp); /* set the seek function */ curl_easy_setopt(curl, CURLOPT_SEEKFUNCTION, my_seek); /* pass the file descriptor to the seek callback as well */ - curl_easy_setopt(curl, CURLOPT_SEEKDATA, (void *) fp); + curl_easy_setopt(curl, CURLOPT_SEEKDATA, (void *)fp); /* enable "uploading" (which means PUT when doing HTTP) */ curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); @@ -149,18 +150,18 @@ int main(int argc, char **argv) /* tell libcurl we can use "any" auth, which lets the lib pick one, but it also costs one extra round-trip and possibly sending of all the PUT - data twice!!! */ + data twice */ curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY); - /* set user name and password for the authentication */ + /* set username and password for the authentication */ curl_easy_setopt(curl, CURLOPT_USERPWD, "user:password"); /* Now run off and do what you have been told! */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); @@ -168,5 +169,5 @@ int main(int argc, char **argv) fclose(fp); /* close the local file */ curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/block_ip.c b/docs/examples/block_ip.c index b99fab58c389..3515acfad7b6 100644 --- a/docs/examples/block_ip.c +++ b/docs/examples/block_ip.c @@ -29,18 +29,16 @@ * filter IP addresses. */ -#if defined(__AMIGA__) || defined(UNDER_CE) +#ifdef __AMIGA__ #include -int main(void) { printf("Platform not supported.\n"); return 1; } +int main(void) +{ + printf("Platform not supported.\n"); + return 1; +} #else #ifdef _WIN32 -#ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif -#ifndef _CRT_NONSTDC_NO_DEPRECATE -#define _CRT_NONSTDC_NO_DEPRECATE -#endif #if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600 #undef _WIN32_WINNT #define _WIN32_WINNT 0x0600 /* Requires Windows Vista */ @@ -48,6 +46,7 @@ int main(void) { printf("Platform not supported.\n"); return 1; } #include #include #include +#define strdup _strdup #else #include #include @@ -269,7 +268,7 @@ static curl_socket_t opensocket(void *clientp, if(ip && filter->type == CONNECTION_FILTER_BLACKLIST) { if(filter->verbose) { - char buf[128] = {0}; + char buf[128] = { 0 }; inet_ntop(address->family, cinaddr, buf, sizeof(buf)); fprintf(stderr, "* Rejecting IP %s due to blacklist entry %s.\n", buf, ip->str); @@ -278,7 +277,7 @@ static curl_socket_t opensocket(void *clientp, } else if(!ip && filter->type == CONNECTION_FILTER_WHITELIST) { if(filter->verbose) { - char buf[128] = {0}; + char buf[128] = { 0 }; inet_ntop(address->family, cinaddr, buf, sizeof(buf)); fprintf(stderr, "* Rejecting IP %s due to missing whitelist entry.\n", buf); @@ -294,17 +293,17 @@ static curl_socket_t opensocket(void *clientp, int main(void) { CURL *curl; - CURLcode res; + CURLcode result; struct connection_filter *filter; filter = (struct connection_filter *)calloc(1, sizeof(*filter)); if(!filter) return 1; - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) { + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) { free(filter); - return (int)res; + return (int)result; } curl = curl_easy_init(); @@ -337,12 +336,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); /* Perform the request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) { + if(result != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); } /* Clean up */ diff --git a/docs/examples/cacertinmem.c b/docs/examples/cacertinmem.c index 5855d872b658..2ede090a26bd 100644 --- a/docs/examples/cacertinmem.c +++ b/docs/examples/cacertinmem.c @@ -28,11 +28,12 @@ /* Requires: USE_OPENSSL */ -#include #include -#include + #include +#include + #if defined(__GNUC__) || defined(__clang__) #pragma GCC diagnostic ignored "-Woverlength-strings" #endif @@ -48,7 +49,7 @@ typedef size_t ossl_valsize_t; typedef int ossl_valsize_t; #endif -static size_t writefunction(void *ptr, size_t size, size_t nmemb, void *stream) +static size_t write_cb(void *ptr, size_t size, size_t nmemb, void *stream) { fwrite(ptr, size, nmemb, (FILE *)stream); return nmemb * size; @@ -81,7 +82,7 @@ static CURLcode sslctx_function(CURL *curl, void *sslctx, void *pointer) BIO *cbio = BIO_new_mem_buf(mypem, sizeof(mypem)); X509_STORE *cts = SSL_CTX_get_cert_store((SSL_CTX *)sslctx); ossl_valsize_t i; - STACK_OF(X509_INFO) *inf; + STACK_OF(X509_INFO) * inf; (void)curl; (void)pointer; @@ -115,38 +116,38 @@ static CURLcode sslctx_function(CURL *curl, void *sslctx, void *pointer) int main(void) { - CURL *ch; - - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; - - ch = curl_easy_init(); - if(ch) { - curl_easy_setopt(ch, CURLOPT_VERBOSE, 0L); - curl_easy_setopt(ch, CURLOPT_HEADER, 0L); - curl_easy_setopt(ch, CURLOPT_NOPROGRESS, 1L); - curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1L); - curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, writefunction); - curl_easy_setopt(ch, CURLOPT_WRITEDATA, stdout); - curl_easy_setopt(ch, CURLOPT_HEADERFUNCTION, writefunction); - curl_easy_setopt(ch, CURLOPT_HEADERDATA, stderr); - 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 *curl; + + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; + + curl = curl_easy_init(); + if(curl) { + curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L); + curl_easy_setopt(curl, CURLOPT_HEADER, 0L); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L); + curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, stdout); + curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, write_cb); + curl_easy_setopt(curl, CURLOPT_HEADERDATA, stderr); + curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM"); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); + curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/"); /* Turn off the default CA locations, otherwise libcurl loads CA * certificates from the locations that were detected/specified at * build-time */ - curl_easy_setopt(ch, CURLOPT_CAINFO, NULL); - curl_easy_setopt(ch, CURLOPT_CAPATH, NULL); + curl_easy_setopt(curl, CURLOPT_CAINFO, NULL); + curl_easy_setopt(curl, CURLOPT_CAPATH, NULL); /* first try: retrieve page without ca certificates -> should fail * unless libcurl was built --with-ca-fallback enabled at build-time */ - res = curl_easy_perform(ch); - if(res == CURLE_OK) + result = curl_easy_perform(curl); + if(result == CURLE_OK) printf("*** transfer succeeded ***\n"); else printf("*** transfer failed ***\n"); @@ -155,25 +156,25 @@ int main(void) * performance of multiple transfers but it is necessary order to * demonstrate this example. recall that the ssl ctx callback is only * called _before_ an SSL connection is established, therefore it does not - * affect existing verified SSL connections already in the connection cache - * associated with this handle. normally you would set the ssl ctx function - * before making any transfers, and not use this option. + * affect existing verified SSL connections already in the connection + * cache associated with this handle. normally you would set the ssl ctx + * function before making any transfers, and not use this option. */ - curl_easy_setopt(ch, CURLOPT_FRESH_CONNECT, 1L); + curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1L); - /* second try: retrieve page using cacerts' certificate -> succeeds to load - * the certificate by installing a function doing the necessary + /* second try: retrieve page using cacerts' certificate -> succeeds to + * load the certificate by installing a function doing the necessary * "modifications" to the SSL CONTEXT just before link init */ - curl_easy_setopt(ch, CURLOPT_SSL_CTX_FUNCTION, sslctx_function); - res = curl_easy_perform(ch); - if(res == CURLE_OK) + curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctx_function); + result = curl_easy_perform(curl); + if(result == CURLE_OK) printf("*** transfer succeeded ***\n"); else printf("*** transfer failed ***\n"); - curl_easy_cleanup(ch); + curl_easy_cleanup(curl); } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/certinfo.c b/docs/examples/certinfo.c index 0443aa42f46c..7dfa8e99c983 100644 --- a/docs/examples/certinfo.c +++ b/docs/examples/certinfo.c @@ -29,7 +29,7 @@ #include -static size_t wrfu(void *ptr, size_t size, size_t nmemb, void *stream) +static size_t write_cb(void *ptr, size_t size, size_t nmemb, void *stream) { (void)stream; (void)ptr; @@ -39,17 +39,17 @@ static size_t wrfu(void *ptr, size_t size, size_t nmemb, void *stream) int main(void) { CURL *curl; - CURLcode res; + CURLcode result; - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/"); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, wrfu); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); @@ -57,14 +57,14 @@ int main(void) curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L); curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { struct curl_certinfo *certinfo; - res = curl_easy_getinfo(curl, CURLINFO_CERTINFO, &certinfo); + result = curl_easy_getinfo(curl, CURLINFO_CERTINFO, &certinfo); - if(!res && certinfo) { + if(!result && certinfo) { int i; printf("%d certs!\n", certinfo->num_of_certs); @@ -74,10 +74,8 @@ int main(void) for(slist = certinfo->certinfo[i]; slist; slist = slist->next) printf("%s\n", slist->data); - } } - } curl_easy_cleanup(curl); @@ -85,5 +83,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/chkspeed.c b/docs/examples/chkspeed.c index 996db393f584..3e8181e16fdd 100644 --- a/docs/examples/chkspeed.c +++ b/docs/examples/chkspeed.c @@ -34,6 +34,11 @@ * dd if=/dev/urandom of=file_1M.bin bs=1M count=1 * */ +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* for ctime() */ +#endif +#endif #include #include @@ -52,7 +57,7 @@ #define CHKSPEED_VERSION "1.0" -static size_t WriteCallback(void *ptr, size_t size, size_t nmemb, void *data) +static size_t write_cb(void *ptr, size_t size, size_t nmemb, void *data) { /* we are not interested in the downloaded bytes itself, so we only return the size we would have saved ... */ @@ -63,8 +68,8 @@ static size_t WriteCallback(void *ptr, size_t size, size_t nmemb, void *data) int main(int argc, char *argv[]) { - CURL *curl_handle; - CURLcode res; + CURL *curl; + CURLcode result; int prtall = 0, prtsep = 0, prttime = 0; const char *url = URL_1M; char *appname = argv[0]; @@ -156,72 +161,76 @@ int main(int argc, char *argv[]) } /* init libcurl */ - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; /* init the curl session */ - curl_handle = curl_easy_init(); - if(curl_handle) { + curl = curl_easy_init(); + if(curl) { /* specify URL to get */ - curl_easy_setopt(curl_handle, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_URL, url); /* send all data to this function */ - curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteCallback); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); /* some servers do not like requests that are made without a user-agent field, so we provide one */ - curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, + curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-speedchecker/" CHKSPEED_VERSION); /* get it! */ - res = curl_easy_perform(curl_handle); + result = curl_easy_perform(curl); - if(CURLE_OK == res) { + if(CURLE_OK == result) { curl_off_t val; /* check for bytes downloaded */ - res = curl_easy_getinfo(curl_handle, CURLINFO_SIZE_DOWNLOAD_T, &val); - if((CURLE_OK == res) && (val > 0)) - printf("Data downloaded: %lu bytes.\n", (unsigned long)val); + result = curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD_T, &val); + if((CURLE_OK == result) && (val > 0)) + printf("Data downloaded: %" CURL_FORMAT_CURL_OFF_T " bytes.\n", val); /* check for total download time */ - res = curl_easy_getinfo(curl_handle, CURLINFO_TOTAL_TIME_T, &val); - if((CURLE_OK == res) && (val > 0)) - printf("Total download time: %lu.%06lu sec.\n", - (unsigned long)(val / 1000000), - (unsigned long)(val % 1000000)); + result = curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME_T, &val); + if((CURLE_OK == result) && (val > 0)) + printf("Total download time: %" CURL_FORMAT_CURL_OFF_T + ".%06" CURL_FORMAT_CURL_OFF_T " sec.\n", + val / 1000000, + val % 1000000); /* check for average download speed */ - res = curl_easy_getinfo(curl_handle, CURLINFO_SPEED_DOWNLOAD_T, &val); - if((CURLE_OK == res) && (val > 0)) - printf("Average download speed: %lu kbyte/sec.\n", - (unsigned long)(val / 1024)); + result = curl_easy_getinfo(curl, CURLINFO_SPEED_DOWNLOAD_T, &val); + if((CURLE_OK == result) && (val > 0)) + printf("Average download speed: " + "%" CURL_FORMAT_CURL_OFF_T " kbyte/sec.\n", + val / 1024); if(prtall) { /* check for name resolution time */ - res = curl_easy_getinfo(curl_handle, CURLINFO_NAMELOOKUP_TIME_T, &val); - if((CURLE_OK == res) && (val > 0)) - printf("Name lookup time: %lu.%06lu sec.\n", - (unsigned long)(val / 1000000), - (unsigned long)(val % 1000000)); + result = curl_easy_getinfo(curl, CURLINFO_NAMELOOKUP_TIME_T, &val); + if((CURLE_OK == result) && (val > 0)) + printf("Name lookup time: %" CURL_FORMAT_CURL_OFF_T + ".%06" CURL_FORMAT_CURL_OFF_T " sec.\n", + val / 1000000, + val % 1000000); /* check for connect time */ - res = curl_easy_getinfo(curl_handle, CURLINFO_CONNECT_TIME_T, &val); - if((CURLE_OK == res) && (val > 0)) - printf("Connect time: %lu.%06lu sec.\n", - (unsigned long)(val / 1000000), - (unsigned long)(val % 1000000)); + result = curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME_T, &val); + if((CURLE_OK == result) && (val > 0)) + printf("Connect time: %" CURL_FORMAT_CURL_OFF_T + ".%06" CURL_FORMAT_CURL_OFF_T " sec.\n", + val / 1000000, + val % 1000000); } } else { fprintf(stderr, "Error while fetching '%s' : %s\n", - url, curl_easy_strerror(res)); + url, curl_easy_strerror(result)); } /* cleanup curl stuff */ - curl_easy_cleanup(curl_handle); + curl_easy_cleanup(curl); } /* we are done with libcurl, so clean it up */ diff --git a/docs/examples/connect-to.c b/docs/examples/connect-to.c index 253c531c420d..d401fca66253 100644 --- a/docs/examples/connect-to.c +++ b/docs/examples/connect-to.c @@ -26,6 +26,7 @@ * */ #include + #include int main(void) @@ -33,14 +34,14 @@ int main(void) struct curl_slist *host; CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; /* 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 + 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. */ /* instead of curl.se:443, it resolves and uses example.com:443 but in other @@ -53,15 +54,15 @@ int main(void) curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); curl_easy_setopt(curl, CURLOPT_URL, "https://curl.se/"); - /* since this connects to the wrong host, checking the host name in the + /* since this connects to the wrong host, checking the hostname in the server certificate fails, so unless we disable the check libcurl returns CURLE_PEER_FAILED_VERIFICATION */ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); - /* Letting the wrong host name in the certificate be okay, the transfer + /* Letting the wrong hostname in the certificate be okay, the transfer goes through but (most likely) causes a 404 or similar because it sends an unknown name in the Host: header field */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* always cleanup */ curl_easy_cleanup(curl); @@ -71,5 +72,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/cookie_interface.c b/docs/examples/cookie_interface.c index cebbd3cdcff0..e894f19665d0 100644 --- a/docs/examples/cookie_interface.c +++ b/docs/examples/cookie_interface.c @@ -25,6 +25,11 @@ * Import and export cookies with COOKIELIST. * */ +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* for _snprintf() */ +#endif +#endif #include #include @@ -39,16 +44,16 @@ static int print_cookies(CURL *curl) { - CURLcode res; + CURLcode result; struct curl_slist *cookies; struct curl_slist *nc; int i; printf("Cookies, curl knows:\n"); - res = curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies); - if(res != CURLE_OK) { - fprintf(stderr, "Curl curl_easy_getinfo failed: %s\n", - curl_easy_strerror(res)); + result = curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies); + if(result != CURLE_OK) { + fprintf(stderr, "curl curl_easy_getinfo failed: %s\n", + curl_easy_strerror(result)); return 1; } nc = cookies; @@ -66,15 +71,14 @@ static int print_cookies(CURL *curl) return 0; } -int -main(void) +int main(void) { CURL *curl; - CURLcode res; + CURLcode result; - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -83,9 +87,9 @@ main(void) curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/"); curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); curl_easy_setopt(curl, CURLOPT_COOKIEFILE, ""); /* start cookie engine */ - res = curl_easy_perform(curl); - if(res != CURLE_OK) { - fprintf(stderr, "Curl perform failed: %s\n", curl_easy_strerror(res)); + result = curl_easy_perform(curl); + if(result != CURLE_OK) { + fprintf(stderr, "curl perform failed: %s\n", curl_easy_strerror(result)); return 1; } @@ -103,10 +107,10 @@ main(void) ".example.com", "TRUE", "/", "FALSE", difftime(time(NULL) + 31337, (time_t)0), "PREF", "hello example, I like you!"); - res = curl_easy_setopt(curl, CURLOPT_COOKIELIST, nline); - if(res != CURLE_OK) { - fprintf(stderr, "Curl curl_easy_setopt failed: %s\n", - curl_easy_strerror(res)); + result = curl_easy_setopt(curl, CURLOPT_COOKIELIST, nline); + if(result != CURLE_OK) { + fprintf(stderr, "curl curl_easy_setopt failed: %s\n", + curl_easy_strerror(result)); return 1; } @@ -118,25 +122,25 @@ main(void) snprintf(nline, sizeof(nline), "Set-Cookie: OLD_PREF=3d141414bf4209321; " "expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/; domain=.example.com"); - res = curl_easy_setopt(curl, CURLOPT_COOKIELIST, nline); - if(res != CURLE_OK) { - fprintf(stderr, "Curl curl_easy_setopt failed: %s\n", - curl_easy_strerror(res)); + result = curl_easy_setopt(curl, CURLOPT_COOKIELIST, nline); + if(result != CURLE_OK) { + fprintf(stderr, "curl curl_easy_setopt failed: %s\n", + curl_easy_strerror(result)); return 1; } print_cookies(curl); - res = curl_easy_perform(curl); - if(res != CURLE_OK) { - fprintf(stderr, "Curl perform failed: %s\n", curl_easy_strerror(res)); + result = curl_easy_perform(curl); + if(result != CURLE_OK) { + fprintf(stderr, "curl perform failed: %s\n", curl_easy_strerror(result)); return 1; } curl_easy_cleanup(curl); } else { - fprintf(stderr, "Curl init failed!\n"); + fprintf(stderr, "curl init failed!\n"); return 1; } diff --git a/docs/examples/crawler.c b/docs/examples/crawler.c index e8dbf244f91e..2b199be1164d 100644 --- a/docs/examples/crawler.c +++ b/docs/examples/crawler.c @@ -20,32 +20,34 @@ * * SPDX-License-Identifier: curl * - * To compile: - * gcc crawler.c $(pkg-config --cflags --libs libxml-2.0 libcurl) - * - */ + ***************************************************************************/ /* * Web crawler based on curl and libxml2 to stress-test curl with * hundreds of concurrent connections to various servers. * */ - +/* + * To compile: + * gcc crawler.c $(pkg-config --cflags --libs libxml-2.0 libcurl) + */ #include #include #include -#include + #include #include #include #include +#include + /* Parameters */ static int max_con = 200; static int max_total = 20000; static int max_requests = 500; static size_t max_link_per_page = 5; static int follow_relative_links = 0; -static const char *start_page = "https://www.reuters.com"; +static const char *start_page = "https://www.reuters.com/"; static int pending_interrupt = 0; static void sighandler(int dummy) @@ -60,10 +62,10 @@ struct memory { size_t size; }; -static size_t grow_buffer(void *contents, size_t sz, size_t nmemb, void *ctx) +static size_t write_cb(void *contents, size_t sz, size_t nmemb, void *ctx) { size_t realsize = sz * nmemb; - struct memory *mem = (struct memory*) ctx; + struct memory *mem = (struct memory *)ctx; char *ptr = realloc(mem->buf, mem->size + realsize); if(!ptr) { /* out of memory */ @@ -78,52 +80,51 @@ static size_t grow_buffer(void *contents, size_t sz, size_t nmemb, void *ctx) static CURL *make_handle(const char *url) { - CURL *handle = curl_easy_init(); + CURL *curl = curl_easy_init(); struct memory *mem; /* Important: use HTTP2 over HTTPS */ - curl_easy_setopt(handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS); - curl_easy_setopt(handle, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS); + curl_easy_setopt(curl, CURLOPT_URL, url); /* buffer body */ mem = malloc(sizeof(*mem)); mem->size = 0; mem->buf = malloc(1); - curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, grow_buffer); - curl_easy_setopt(handle, CURLOPT_WRITEDATA, mem); - curl_easy_setopt(handle, CURLOPT_PRIVATE, mem); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, mem); + curl_easy_setopt(curl, CURLOPT_PRIVATE, mem); /* For completeness */ - curl_easy_setopt(handle, CURLOPT_ACCEPT_ENCODING, ""); - curl_easy_setopt(handle, CURLOPT_TIMEOUT, 5L); - curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, ""); + curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5L); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); /* only allow redirects to HTTP and HTTPS URLs */ - curl_easy_setopt(handle, CURLOPT_REDIR_PROTOCOLS_STR, "http,https"); - curl_easy_setopt(handle, CURLOPT_AUTOREFERER, 1L); - curl_easy_setopt(handle, CURLOPT_MAXREDIRS, 10L); + curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS_STR, "http,https"); + curl_easy_setopt(curl, CURLOPT_AUTOREFERER, 1L); + curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 10L); /* each transfer needs to be done within 20 seconds! */ - curl_easy_setopt(handle, CURLOPT_TIMEOUT_MS, 20000L); + curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 20000L); /* connect fast or fail */ - curl_easy_setopt(handle, CURLOPT_CONNECTTIMEOUT_MS, 2000L); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, 2000L); /* skip files larger than a gigabyte */ - curl_easy_setopt(handle, CURLOPT_MAXFILESIZE_LARGE, - (curl_off_t)1024*1024*1024); - curl_easy_setopt(handle, CURLOPT_COOKIEFILE, ""); - curl_easy_setopt(handle, CURLOPT_FILETIME, 1L); - curl_easy_setopt(handle, CURLOPT_USERAGENT, "mini crawler"); - curl_easy_setopt(handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY); - curl_easy_setopt(handle, CURLOPT_UNRESTRICTED_AUTH, 1L); - curl_easy_setopt(handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY); - curl_easy_setopt(handle, CURLOPT_EXPECT_100_TIMEOUT_MS, 0L); - return handle; + curl_easy_setopt(curl, CURLOPT_MAXFILESIZE_LARGE, + (curl_off_t)1024 * 1024 * 1024); + curl_easy_setopt(curl, CURLOPT_COOKIEFILE, ""); + curl_easy_setopt(curl, CURLOPT_FILETIME, 1L); + curl_easy_setopt(curl, CURLOPT_USERAGENT, "mini crawler"); + curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY); + curl_easy_setopt(curl, CURLOPT_UNRESTRICTED_AUTH, 1L); + curl_easy_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_ANY); + curl_easy_setopt(curl, CURLOPT_EXPECT_100_TIMEOUT_MS, 0L); + return curl; } /* HREF finder implemented in libxml2 but could be any HTML parser */ -static size_t follow_links(CURLM *multi_handle, struct memory *mem, - const char *url) +static size_t follow_links(CURLM *multi, struct memory *mem, const char *url) { - int opts = HTML_PARSE_NOBLANKS | HTML_PARSE_NOERROR | \ - HTML_PARSE_NOWARNING | HTML_PARSE_NONET; + int opts = HTML_PARSE_NOBLANKS | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING | + HTML_PARSE_NONET; htmlDocPtr doc = htmlReadMemory(mem->buf, (int)mem->size, url, NULL, opts); size_t count; int i; @@ -133,7 +134,7 @@ static size_t follow_links(CURLM *multi_handle, struct memory *mem, xmlXPathObjectPtr result; if(!doc) return 0; - xpath = (xmlChar*) "//a/@href"; + xpath = (xmlChar *)"//a/@href"; context = xmlXPathNewContext(doc); result = xmlXPathEvalExpression(xpath, context); xmlXPathFreeContext(context); @@ -153,14 +154,14 @@ static size_t follow_links(CURLM *multi_handle, struct memory *mem, char *link; if(follow_relative_links) { xmlChar *orig = href; - href = xmlBuildURI(href, (xmlChar *) url); + href = xmlBuildURI(href, (xmlChar *)url); xmlFree(orig); } - link = (char *) href; + link = (char *)href; if(!link || strlen(link) < 20) continue; if(!strncmp(link, "http://", 7) || !strncmp(link, "https://", 8)) { - curl_multi_add_handle(multi_handle, make_handle(link)); + curl_multi_add_handle(multi, make_handle(link)); if(count++ == max_link_per_page) break; } @@ -170,38 +171,38 @@ static size_t follow_links(CURLM *multi_handle, struct memory *mem, return count; } -static int is_html(char *ctype) +static int is_html(const char *ctype) { return ctype != NULL && strlen(ctype) > 10 && strstr(ctype, "text/html"); } int main(void) { - CURLM *multi_handle; + CURLM *multi; int msgs_left; int pending; int complete; int still_running; - CURLcode res; + CURLcode result; - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; signal(SIGINT, sighandler); LIBXML_TEST_VERSION - multi_handle = curl_multi_init(); - if(multi_handle) { - curl_multi_setopt(multi_handle, CURLMOPT_MAX_TOTAL_CONNECTIONS, max_con); - curl_multi_setopt(multi_handle, CURLMOPT_MAX_HOST_CONNECTIONS, 6L); + multi = curl_multi_init(); + if(multi) { + curl_multi_setopt(multi, CURLMOPT_MAX_TOTAL_CONNECTIONS, max_con); + curl_multi_setopt(multi, CURLMOPT_MAX_HOST_CONNECTIONS, 6L); /* enables http/2 if available */ #ifdef CURLPIPE_MULTIPLEX - curl_multi_setopt(multi_handle, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX); + curl_multi_setopt(multi, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX); #endif /* sets html start page */ - curl_multi_add_handle(multi_handle, make_handle(start_page)); + curl_multi_add_handle(multi, make_handle(start_page)); pending = 0; complete = 0; @@ -210,42 +211,42 @@ int main(void) int numfds; CURLMsg *m; - curl_multi_wait(multi_handle, NULL, 0, 1000, &numfds); - curl_multi_perform(multi_handle, &still_running); + curl_multi_wait(multi, NULL, 0, 1000, &numfds); + curl_multi_perform(multi, &still_running); /* See how the transfers went */ m = NULL; - while((m = curl_multi_info_read(multi_handle, &msgs_left))) { + while((m = curl_multi_info_read(multi, &msgs_left))) { if(m->msg == CURLMSG_DONE) { - CURL *handle = m->easy_handle; + CURL *curl = m->easy_handle; char *url; struct memory *mem; - curl_easy_getinfo(handle, CURLINFO_PRIVATE, &mem); - curl_easy_getinfo(handle, CURLINFO_EFFECTIVE_URL, &url); + curl_easy_getinfo(curl, CURLINFO_PRIVATE, &mem); + curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url); if(m->data.result == CURLE_OK) { long res_status; - curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &res_status); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &res_status); if(res_status == 200) { char *ctype; - curl_easy_getinfo(handle, CURLINFO_CONTENT_TYPE, &ctype); + curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ctype); printf("[%d] HTTP 200 (%s): %s\n", complete, ctype, url); if(is_html(ctype) && mem->size > 100) { if(pending < max_requests && (complete + pending) < max_total) { - pending += follow_links(multi_handle, mem, url); + pending += follow_links(multi, mem, url); still_running = 1; } } } else { - printf("[%d] HTTP %d: %s\n", complete, (int) res_status, url); + printf("[%d] HTTP %d: %s\n", complete, (int)res_status, url); } } else { printf("[%d] Connection failure: %s\n", complete, url); } - curl_multi_remove_handle(multi_handle, handle); - curl_easy_cleanup(handle); + curl_multi_remove_handle(multi, curl); + curl_easy_cleanup(curl); free(mem->buf); free(mem); complete++; @@ -253,7 +254,7 @@ int main(void) } } } - curl_multi_cleanup(multi_handle); + curl_multi_cleanup(multi); } curl_global_cleanup(); return 0; diff --git a/docs/examples/debug.c b/docs/examples/debug.c index 3c8355df05cf..e49910a5fc0b 100644 --- a/docs/examples/debug.c +++ b/docs/examples/debug.c @@ -26,6 +26,7 @@ * */ #include + #include struct data { @@ -69,7 +70,7 @@ static void dump(const char *text, FILE *stream, unsigned char *ptr, } fprintf(stream, "%c", (ptr[i + c] >= 0x20) && (ptr[i + c] < 0x80) ? ptr[i + c] : '.'); - /* check again for 0D0A, to avoid an extra \n if it's at width */ + /* check again for 0D0A, to avoid an extra \n if it is at width */ if(nohex && (i + c + 2 < size) && ptr[i + c + 1] == 0x0D && ptr[i + c + 2] == 0x0A) { i += (c + 3 - width); @@ -81,12 +82,12 @@ static void dump(const char *text, FILE *stream, unsigned char *ptr, fflush(stream); } -static int my_trace(CURL *handle, curl_infotype type, +static int my_trace(CURL *curl, curl_infotype type, char *data, size_t size, void *userp) { struct data *config = (struct data *)userp; const char *text; - (void)handle; + (void)curl; switch(type) { case CURLINFO_TEXT: @@ -121,12 +122,12 @@ static int my_trace(CURL *handle, curl_infotype type, int main(void) { CURL *curl; - CURLcode res; + CURLcode result; struct data config; - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; config.trace_ascii = 1; /* enable ASCII tracing */ @@ -142,15 +143,15 @@ int main(void) curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/default-scheme.c b/docs/examples/default-scheme.c index b4ea5fa3bfb4..821cad78c2d1 100644 --- a/docs/examples/default-scheme.c +++ b/docs/examples/default-scheme.c @@ -26,16 +26,17 @@ * */ #include + #include int main(void) { CURL *curl; - CURLcode res; + CURLcode result; - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -47,16 +48,16 @@ int main(void) curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/ephiperfifo.c b/docs/examples/ephiperfifo.c index c22a3601010e..f5b5913747f3 100644 --- a/docs/examples/ephiperfifo.c +++ b/docs/examples/ephiperfifo.c @@ -41,7 +41,6 @@ Whenever there is input into the fifo, the program reads the input as a list of URL's and creates some new easy handles to fetch each URL via the curl_multi "hiper" API. - Thus, you can try a single URL: % echo http://www.yahoo.com > hiper.fifo @@ -58,7 +57,6 @@ This is purely a demo app, all retrieved data is simply discarded by the write callback. */ - #include #include #include @@ -77,7 +75,6 @@ callback. #define MSG_OUT stdout /* Send info to stdout, change to stderr if you want */ - /* Global information, common to all connections */ struct GlobalInfo { int epfd; /* epoll filedescriptor */ @@ -90,7 +87,7 @@ struct GlobalInfo { /* Information associated with a specific easy handle */ struct ConnInfo { - CURL *easy; + CURL *curl; char *url; struct GlobalInfo *global; char error[CURL_ERROR_SIZE]; @@ -99,29 +96,41 @@ struct ConnInfo { /* Information associated with a specific socket */ struct SockInfo { curl_socket_t sockfd; - CURL *easy; + CURL *curl; int action; long timeout; struct GlobalInfo *global; }; -#define mycase(code) \ - case code: s = __STRING(code) - /* Die if we get a bad CURLMcode somewhere */ static void mcode_or_die(const char *where, CURLMcode code) { if(CURLM_OK != code) { const char *s; switch(code) { - mycase(CURLM_BAD_HANDLE); break; - mycase(CURLM_BAD_EASY_HANDLE); break; - mycase(CURLM_OUT_OF_MEMORY); break; - mycase(CURLM_INTERNAL_ERROR); break; - mycase(CURLM_UNKNOWN_OPTION); break; - mycase(CURLM_LAST); break; - default: s = "CURLM_unknown"; break; - mycase(CURLM_BAD_SOCKET); + case CURLM_BAD_HANDLE: + s = "CURLM_BAD_HANDLE"; + break; + case CURLM_BAD_EASY_HANDLE: + s = "CURLM_BAD_EASY_HANDLE"; + break; + case CURLM_OUT_OF_MEMORY: + s = "CURLM_OUT_OF_MEMORY"; + break; + case CURLM_INTERNAL_ERROR: + s = "CURLM_INTERNAL_ERROR"; + break; + case CURLM_UNKNOWN_OPTION: + s = "CURLM_UNKNOWN_OPTION"; + break; + case CURLM_LAST: + s = "CURLM_LAST"; + break; + default: + s = "CURLM_unknown"; + break; + case CURLM_BAD_SOCKET: + s = "CURLM_BAD_SOCKET"; fprintf(MSG_OUT, "ERROR: %s returns %s\n", where, s); /* ignore this error */ return; @@ -133,7 +142,7 @@ static void mcode_or_die(const char *where, CURLMcode code) static void timer_cb(struct GlobalInfo *g, int revents); -/* Update the timer after curl_multi library does its thing. Curl informs the +/* Update the timer after curl_multi library does its thing. curl informs the * application through this callback what it wants the new timeout to be, * after it does some work. */ static int multi_timer_cb(CURLM *multi, long timeout_ms, struct GlobalInfo *g) @@ -161,7 +170,7 @@ static int multi_timer_cb(CURLM *multi, long timeout_ms, struct GlobalInfo *g) memset(&its, 0, sizeof(its)); } - timerfd_settime(g->tfd, /* flags= */0, &its, NULL); + timerfd_settime(g->tfd, /* flags= */ 0, &its, NULL); return 0; } @@ -172,20 +181,18 @@ static void check_multi_info(struct GlobalInfo *g) CURLMsg *msg; int msgs_left; struct ConnInfo *conn; - CURL *easy; - CURLcode res; fprintf(MSG_OUT, "REMAINING: %d\n", g->still_running); while((msg = curl_multi_info_read(g->multi, &msgs_left))) { if(msg->msg == CURLMSG_DONE) { - easy = msg->easy_handle; - res = msg->data.result; - curl_easy_getinfo(easy, CURLINFO_PRIVATE, &conn); - curl_easy_getinfo(easy, CURLINFO_EFFECTIVE_URL, &eff_url); - fprintf(MSG_OUT, "DONE: %s => (%d) %s\n", eff_url, res, conn->error); - curl_multi_remove_handle(g->multi, easy); + CURL *curl = msg->easy_handle; + CURLcode result = msg->data.result; + curl_easy_getinfo(curl, CURLINFO_PRIVATE, &conn); + curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &eff_url); + fprintf(MSG_OUT, "DONE: %s => (%d) %s\n", eff_url, result, conn->error); + curl_multi_remove_handle(g->multi, curl); free(conn->url); - curl_easy_cleanup(easy); + curl_easy_cleanup(curl); free(conn); } } @@ -194,14 +201,14 @@ static void check_multi_info(struct GlobalInfo *g) /* Called by libevent when we get action on a multi socket filedescriptor */ static void event_cb(struct GlobalInfo *g, int fd, int revents) { - CURLMcode rc; + CURLMcode mresult; struct itimerspec its; int action = ((revents & EPOLLIN) ? CURL_CSELECT_IN : 0) | - ((revents & EPOLLOUT) ? CURL_CSELECT_OUT : 0); + ((revents & EPOLLOUT) ? CURL_CSELECT_OUT : 0); - rc = curl_multi_socket_action(g->multi, fd, action, &g->still_running); - mcode_or_die("event_cb: curl_multi_socket_action", rc); + mresult = curl_multi_socket_action(g->multi, fd, action, &g->still_running); + mcode_or_die("event_cb: curl_multi_socket_action", mresult); check_multi_info(g); if(g->still_running <= 0) { @@ -214,14 +221,14 @@ static void event_cb(struct GlobalInfo *g, int fd, int revents) /* Called by main loop when our timeout expires */ static void timer_cb(struct GlobalInfo *g, int revents) { - CURLMcode rc; + CURLMcode mresult; uint64_t count = 0; ssize_t err = 0; err = read(g->tfd, &count, sizeof(uint64_t)); if(err == -1) { /* Note that we may call the timer callback even if the timerfd is not - * readable. It's possible that there are multiple events stored in the + * readable. It is possible that there are multiple events stored in the * epoll buffer (i.e. the timer may have fired multiple times). The event * count is cleared after the first call so future events in the epoll * buffer fails to read from the timer. */ @@ -235,9 +242,9 @@ static void timer_cb(struct GlobalInfo *g, int revents) perror("read(tfd)"); } - rc = curl_multi_socket_action(g->multi, - CURL_SOCKET_TIMEOUT, 0, &g->still_running); - mcode_or_die("timer_cb: curl_multi_socket_action", rc); + mresult = curl_multi_socket_action(g->multi, + CURL_SOCKET_TIMEOUT, 0, &g->still_running); + mcode_or_die("timer_cb: curl_multi_socket_action", mresult); check_multi_info(g); } @@ -270,7 +277,7 @@ static void setsock(struct SockInfo *f, curl_socket_t s, CURL *e, int act, f->sockfd = s; f->action = act; - f->easy = e; + f->curl = e; ev.events = kind; ev.data.fd = s; @@ -280,25 +287,24 @@ static void setsock(struct SockInfo *f, curl_socket_t s, CURL *e, int act, } /* Initialize a new SockInfo structure */ -static void addsock(curl_socket_t s, CURL *easy, int action, +static void addsock(curl_socket_t s, CURL *curl, int action, struct GlobalInfo *g) { - struct SockInfo *fdp = (struct SockInfo*)calloc(1, sizeof(struct SockInfo)); + struct SockInfo *fdp = (struct SockInfo *)calloc(1, sizeof(struct SockInfo)); fdp->global = g; - setsock(fdp, s, easy, action, g); + setsock(fdp, s, curl, action, g); curl_multi_assign(g->multi, s, fdp); } /* CURLMOPT_SOCKETFUNCTION */ static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp) { - struct GlobalInfo *g = (struct GlobalInfo*) cbp; - struct SockInfo *fdp = (struct SockInfo*) sockp; - const char *whatstr[]={ "none", "IN", "OUT", "INOUT", "REMOVE" }; + struct GlobalInfo *g = (struct GlobalInfo *)cbp; + struct SockInfo *fdp = (struct SockInfo *)sockp; + const char *whatstr[] = { "none", "IN", "OUT", "INOUT", "REMOVE" }; - fprintf(MSG_OUT, - "socket callback: s=%d e=%p what=%s ", s, e, whatstr[what]); + fprintf(MSG_OUT, "socket callback: s=%d e=%p what=%s ", s, e, whatstr[what]); if(what == CURL_POLL_REMOVE) { fprintf(MSG_OUT, "\n"); remsock(fdp, g); @@ -309,8 +315,7 @@ static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp) addsock(s, e, what, g); } else { - fprintf(MSG_OUT, - "Changing action from %s to %s\n", + fprintf(MSG_OUT, "Changing action from %s to %s\n", whatstr[fdp->action], whatstr[what]); setsock(fdp, s, e, what, g); } @@ -342,34 +347,34 @@ static int prog_cb(void *p, double dltotal, double dlnow, double ult, static void new_conn(const char *url, struct GlobalInfo *g) { struct ConnInfo *conn; - CURLMcode rc; + CURLMcode mresult; - conn = (struct ConnInfo*)calloc(1, sizeof(*conn)); + conn = (struct ConnInfo *)calloc(1, sizeof(*conn)); conn->error[0] = '\0'; - conn->easy = curl_easy_init(); - if(!conn->easy) { + conn->curl = curl_easy_init(); + if(!conn->curl) { fprintf(MSG_OUT, "curl_easy_init() failed, exiting!\n"); exit(2); } conn->global = g; conn->url = strdup(url); - curl_easy_setopt(conn->easy, CURLOPT_URL, conn->url); - curl_easy_setopt(conn->easy, CURLOPT_WRITEFUNCTION, write_cb); - curl_easy_setopt(conn->easy, CURLOPT_WRITEDATA, conn); - curl_easy_setopt(conn->easy, CURLOPT_VERBOSE, 1L); - curl_easy_setopt(conn->easy, CURLOPT_ERRORBUFFER, conn->error); - curl_easy_setopt(conn->easy, CURLOPT_PRIVATE, conn); - curl_easy_setopt(conn->easy, CURLOPT_NOPROGRESS, 0L); - curl_easy_setopt(conn->easy, CURLOPT_PROGRESSFUNCTION, prog_cb); - curl_easy_setopt(conn->easy, CURLOPT_PROGRESSDATA, conn); - curl_easy_setopt(conn->easy, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt(conn->easy, CURLOPT_LOW_SPEED_TIME, 3L); - curl_easy_setopt(conn->easy, CURLOPT_LOW_SPEED_LIMIT, 10L); - fprintf(MSG_OUT, - "Adding easy %p to multi %p (%s)\n", conn->easy, g->multi, url); - rc = curl_multi_add_handle(g->multi, conn->easy); - mcode_or_die("new_conn: curl_multi_add_handle", rc); + curl_easy_setopt(conn->curl, CURLOPT_URL, conn->url); + curl_easy_setopt(conn->curl, CURLOPT_WRITEFUNCTION, write_cb); + curl_easy_setopt(conn->curl, CURLOPT_WRITEDATA, conn); + curl_easy_setopt(conn->curl, CURLOPT_VERBOSE, 1L); + curl_easy_setopt(conn->curl, CURLOPT_ERRORBUFFER, conn->error); + curl_easy_setopt(conn->curl, CURLOPT_PRIVATE, conn); + curl_easy_setopt(conn->curl, CURLOPT_NOPROGRESS, 0L); + curl_easy_setopt(conn->curl, CURLOPT_PROGRESSFUNCTION, prog_cb); + curl_easy_setopt(conn->curl, CURLOPT_PROGRESSDATA, conn); + curl_easy_setopt(conn->curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(conn->curl, CURLOPT_LOW_SPEED_TIME, 3L); + curl_easy_setopt(conn->curl, CURLOPT_LOW_SPEED_LIMIT, 10L); + fprintf(MSG_OUT, "Adding easy %p to multi %p (%s)\n", + conn->curl, g->multi, url); + mresult = curl_multi_add_handle(g->multi, conn->curl); + mcode_or_die("new_conn: curl_multi_add_handle", mresult); /* note that the add_handle() sets a timeout to trigger soon so that the * necessary socket_action() call gets called by this app */ @@ -383,9 +388,9 @@ static void fifo_cb(struct GlobalInfo *g, int revents) int n = 0; do { - s[0]='\0'; + s[0] = '\0'; rv = fscanf(g->input, "%1023s%n", s, &n); - s[n]='\0'; + s[n] = '\0'; if(n && s[0]) { new_conn(s, g); /* if we read a URL, go get it! */ } @@ -439,7 +444,6 @@ static void clean_fifo(struct GlobalInfo *g) unlink(fifo); } - int g_should_exit_ = 0; void sigint_handler(int signo) @@ -447,19 +451,17 @@ void sigint_handler(int signo) g_should_exit_ = 1; } -int main(int argc, char **argv) +int main(void) { - CURLcode res; + CURLcode result; struct GlobalInfo g; struct itimerspec its; struct epoll_event ev; struct epoll_event events[10]; - (void)argc; - (void)argv; - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; g_should_exit_ = 0; signal(SIGINT, sigint_handler); @@ -508,7 +510,7 @@ int main(int argc, char **argv) while(!g_should_exit_) { int idx; int err = epoll_wait(g.epfd, events, - sizeof(events)/sizeof(struct epoll_event), 10000); + sizeof(events) / sizeof(struct epoll_event), 10000); if(err == -1) { /* !checksrc! disable ERRNOVAR 1 */ if(errno == EINTR) { diff --git a/docs/examples/evhiperfifo.c b/docs/examples/evhiperfifo.c index 79dfd3452178..aecbfe8f15c9 100644 --- a/docs/examples/evhiperfifo.c +++ b/docs/examples/evhiperfifo.c @@ -44,7 +44,6 @@ Whenever there is input into the fifo, the program reads the input as a list of URL's and creates some new easy handles to fetch each URL via the curl_multi "hiper" API. - Thus, you can try a single URL: % echo http://www.yahoo.com > hiper.fifo @@ -61,22 +60,22 @@ This is purely a demo app, all retrieved data is simply discarded by the write callback. */ - +#include +#include #include -#include #include +#include +#include +#include #include #include #include -#include -#include + #include -#include -#include -#include -#define MSG_OUT stdout /* Send info to stdout, change to stderr if you want */ +#include +#define MSG_OUT stdout /* Send info to stdout, change to stderr if you want */ /* Global information, common to all connections */ struct GlobalInfo { @@ -90,7 +89,7 @@ struct GlobalInfo { /* Information associated with a specific easy handle */ struct ConnInfo { - CURL *easy; + CURL *curl; char *url; struct GlobalInfo *global; char error[CURL_ERROR_SIZE]; @@ -99,7 +98,7 @@ struct ConnInfo { /* Information associated with a specific socket */ struct SockInfo { curl_socket_t sockfd; - CURL *easy; + CURL *curl; int action; long timeout; struct ev_io ev; @@ -117,7 +116,7 @@ static int multi_timer_cb(CURLM *multi, long timeout_ms, struct GlobalInfo *g) ev_timer_stop(g->loop, &g->timer_event); if(timeout_ms >= 0) { /* -1 means delete, other values are timeout times in milliseconds */ - double t = timeout_ms / 1000; + double t = timeout_ms / 1000; ev_timer_init(&g->timer_event, timer_cb, t, 0.); ev_timer_start(g->loop, &g->timer_event); } @@ -169,20 +168,18 @@ static void check_multi_info(struct GlobalInfo *g) CURLMsg *msg; int msgs_left; struct ConnInfo *conn; - CURL *easy; - CURLcode res; fprintf(MSG_OUT, "REMAINING: %d\n", g->still_running); while((msg = curl_multi_info_read(g->multi, &msgs_left))) { if(msg->msg == CURLMSG_DONE) { - easy = msg->easy_handle; - res = msg->data.result; - curl_easy_getinfo(easy, CURLINFO_PRIVATE, &conn); - curl_easy_getinfo(easy, CURLINFO_EFFECTIVE_URL, &eff_url); - fprintf(MSG_OUT, "DONE: %s => (%d) %s\n", eff_url, res, conn->error); - curl_multi_remove_handle(g->multi, easy); + CURL *curl = msg->easy_handle; + CURLcode result = msg->data.result; + curl_easy_getinfo(curl, CURLINFO_PRIVATE, &conn); + curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &eff_url); + fprintf(MSG_OUT, "DONE: %s => (%d) %s\n", eff_url, result, conn->error); + curl_multi_remove_handle(g->multi, curl); free(conn->url); - curl_easy_cleanup(easy); + curl_easy_cleanup(curl); free(conn); } } @@ -192,16 +189,17 @@ static void check_multi_info(struct GlobalInfo *g) static void event_cb(EV_P_ struct ev_io *w, int revents) { struct GlobalInfo *g; - CURLMcode rc; + CURLMcode mresult; int action; printf("%s w %p revents %i\n", __PRETTY_FUNCTION__, (void *)w, revents); - g = (struct GlobalInfo*) w->data; + g = (struct GlobalInfo *)w->data; action = ((revents & EV_READ) ? CURL_POLL_IN : 0) | ((revents & EV_WRITE) ? CURL_POLL_OUT : 0); - rc = curl_multi_socket_action(g->multi, w->fd, action, &g->still_running); - mcode_or_die("event_cb: curl_multi_socket_action", rc); + mresult = curl_multi_socket_action(g->multi, w->fd, action, + &g->still_running); + mcode_or_die("event_cb: curl_multi_socket_action", mresult); check_multi_info(g); if(g->still_running <= 0) { fprintf(MSG_OUT, "last transfer done, kill timeout\n"); @@ -213,15 +211,15 @@ static void event_cb(EV_P_ struct ev_io *w, int revents) static void timer_cb(EV_P_ struct ev_timer *w, int revents) { struct GlobalInfo *g; - CURLMcode rc; + CURLMcode mresult; printf("%s w %p revents %i\n", __PRETTY_FUNCTION__, (void *)w, revents); g = (struct GlobalInfo *)w->data; - rc = curl_multi_socket_action(g->multi, CURL_SOCKET_TIMEOUT, 0, + mresult = curl_multi_socket_action(g->multi, CURL_SOCKET_TIMEOUT, 0, &g->still_running); - mcode_or_die("timer_cb: curl_multi_socket_action", rc); + mcode_or_die("timer_cb: curl_multi_socket_action", mresult); check_multi_info(g); } @@ -247,7 +245,7 @@ static void setsock(struct SockInfo *f, curl_socket_t s, CURL *e, int act, f->sockfd = s; f->action = act; - f->easy = e; + f->curl = e; if(f->evset) ev_io_stop(g->loop, &f->ev); ev_io_init(&f->ev, event_cb, f->sockfd, kind); @@ -257,28 +255,27 @@ static void setsock(struct SockInfo *f, curl_socket_t s, CURL *e, int act, } /* Initialize a new SockInfo structure */ -static void addsock(curl_socket_t s, CURL *easy, int action, +static void addsock(curl_socket_t s, CURL *curl, int action, struct GlobalInfo *g) { struct SockInfo *fdp = calloc(1, sizeof(struct SockInfo)); fdp->global = g; - setsock(fdp, s, easy, action, g); + setsock(fdp, s, curl, action, g); curl_multi_assign(g->multi, s, fdp); } /* CURLMOPT_SOCKETFUNCTION */ static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp) { - struct GlobalInfo *g = (struct GlobalInfo*) cbp; - struct SockInfo *fdp = (struct SockInfo*) sockp; - const char *whatstr[]={ "none", "IN", "OUT", "INOUT", "REMOVE"}; + struct GlobalInfo *g = (struct GlobalInfo *)cbp; + struct SockInfo *fdp = (struct SockInfo *)sockp; + const char *whatstr[] = { "none", "IN", "OUT", "INOUT", "REMOVE" }; printf("%s e %p s %i what %i cbp %p sockp %p\n", __PRETTY_FUNCTION__, e, s, what, cbp, sockp); - fprintf(MSG_OUT, - "socket callback: s=%d e=%p what=%s ", s, e, whatstr[what]); + fprintf(MSG_OUT, "socket callback: s=%d e=%p what=%s ", s, e, whatstr[what]); if(what == CURL_POLL_REMOVE) { fprintf(MSG_OUT, "\n"); remsock(fdp, g); @@ -289,8 +286,7 @@ static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp) addsock(s, e, what, g); } else { - fprintf(MSG_OUT, - "Changing action from %s to %s\n", + fprintf(MSG_OUT, "Changing action from %s to %s\n", whatstr[fdp->action], whatstr[what]); setsock(fdp, s, e, what, g); } @@ -302,7 +298,7 @@ static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp) static size_t write_cb(void *ptr, size_t size, size_t nmemb, void *data) { size_t realsize = size * nmemb; - struct ConnInfo *conn = (struct ConnInfo*) data; + struct ConnInfo *conn = (struct ConnInfo *)data; (void)ptr; (void)conn; return realsize; @@ -316,8 +312,9 @@ static int xferinfo_cb(void *p, curl_off_t dltotal, curl_off_t dlnow, (void)ult; (void)uln; - fprintf(MSG_OUT, "Progress: %s (%" CURL_FORMAT_CURL_OFF_T - "/%" CURL_FORMAT_CURL_OFF_T ")\n", conn->url, dlnow, dltotal); + fprintf(MSG_OUT, "Progress: %s (%" CURL_FORMAT_CURL_OFF_T "/" + "%" CURL_FORMAT_CURL_OFF_T ")\n", + conn->url, dlnow, dltotal); return 0; } @@ -325,34 +322,34 @@ static int xferinfo_cb(void *p, curl_off_t dltotal, curl_off_t dlnow, static void new_conn(const char *url, struct GlobalInfo *g) { struct ConnInfo *conn; - CURLMcode rc; + CURLMcode mresult; conn = calloc(1, sizeof(*conn)); - conn->error[0]='\0'; + conn->error[0] = '\0'; - conn->easy = curl_easy_init(); - if(!conn->easy) { + conn->curl = curl_easy_init(); + if(!conn->curl) { fprintf(MSG_OUT, "curl_easy_init() failed, exiting!\n"); exit(2); } conn->global = g; conn->url = strdup(url); - curl_easy_setopt(conn->easy, CURLOPT_URL, conn->url); - curl_easy_setopt(conn->easy, CURLOPT_WRITEFUNCTION, write_cb); - curl_easy_setopt(conn->easy, CURLOPT_WRITEDATA, conn); - curl_easy_setopt(conn->easy, CURLOPT_VERBOSE, 1L); - curl_easy_setopt(conn->easy, CURLOPT_ERRORBUFFER, conn->error); - curl_easy_setopt(conn->easy, CURLOPT_PRIVATE, conn); - curl_easy_setopt(conn->easy, CURLOPT_NOPROGRESS, 0L); - curl_easy_setopt(conn->easy, CURLOPT_XFERINFOFUNCTION, xferinfo_cb); - curl_easy_setopt(conn->easy, CURLOPT_PROGRESSDATA, conn); - curl_easy_setopt(conn->easy, CURLOPT_LOW_SPEED_TIME, 3L); - curl_easy_setopt(conn->easy, CURLOPT_LOW_SPEED_LIMIT, 10L); - - fprintf(MSG_OUT, - "Adding easy %p to multi %p (%s)\n", conn->easy, g->multi, url); - rc = curl_multi_add_handle(g->multi, conn->easy); - mcode_or_die("new_conn: curl_multi_add_handle", rc); + curl_easy_setopt(conn->curl, CURLOPT_URL, conn->url); + curl_easy_setopt(conn->curl, CURLOPT_WRITEFUNCTION, write_cb); + curl_easy_setopt(conn->curl, CURLOPT_WRITEDATA, conn); + curl_easy_setopt(conn->curl, CURLOPT_VERBOSE, 1L); + curl_easy_setopt(conn->curl, CURLOPT_ERRORBUFFER, conn->error); + curl_easy_setopt(conn->curl, CURLOPT_PRIVATE, conn); + curl_easy_setopt(conn->curl, CURLOPT_NOPROGRESS, 0L); + curl_easy_setopt(conn->curl, CURLOPT_XFERINFOFUNCTION, xferinfo_cb); + curl_easy_setopt(conn->curl, CURLOPT_PROGRESSDATA, conn); + curl_easy_setopt(conn->curl, CURLOPT_LOW_SPEED_TIME, 3L); + curl_easy_setopt(conn->curl, CURLOPT_LOW_SPEED_LIMIT, 10L); + + fprintf(MSG_OUT, "Adding easy %p to multi %p (%s)\n", + conn->curl, g->multi, url); + mresult = curl_multi_add_handle(g->multi, conn->curl); + mcode_or_die("new_conn: curl_multi_add_handle", mresult); /* note that add_handle() sets a timeout to trigger soon so that the necessary socket_action() gets called */ @@ -369,9 +366,9 @@ static void fifo_cb(EV_P_ struct ev_io *w, int revents) (void)revents; do { - s[0]='\0'; + s[0] = '\0'; rv = fscanf(g->input, "%1023s%n", s, &n); - s[n]='\0'; + s[n] = '\0'; if(n && s[0]) { new_conn(s, g); /* if we read a URL, go get it! */ } @@ -413,16 +410,14 @@ static int init_fifo(struct GlobalInfo *g) return 0; } -int main(int argc, char **argv) +int main(void) { - CURLcode res; + CURLcode result; struct GlobalInfo g; - (void)argc; - (void)argv; - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; memset(&g, 0, sizeof(g)); g.loop = ev_default_loop(0); diff --git a/docs/examples/externalsocket.c b/docs/examples/externalsocket.c index 99e719b74574..d1bdd732b973 100644 --- a/docs/examples/externalsocket.c +++ b/docs/examples/externalsocket.c @@ -26,6 +26,9 @@ * */ #ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* for strerror() */ +#endif #ifndef _WINSOCK_DEPRECATED_NO_WARNINGS #define _WINSOCK_DEPRECATED_NO_WARNINGS /* for inet_addr() */ #endif @@ -34,33 +37,30 @@ #include #include #include + #include #ifdef _WIN32 #define close closesocket #else -#include /* socket types */ -#include /* socket definitions */ +#include /* socket types */ +#include /* socket definitions */ #include -#include /* inet (3) functions */ -#include /* misc. Unix functions */ +#include /* inet (3) functions */ +#include /* misc. Unix functions */ #endif -#ifdef UNDER_CE -#define strerror(e) "?" -#else #include -#endif /* The IP address and port number to connect to */ -#define IPADDR "127.0.0.1" +#define IPADDR "127.0.0.1" #define PORTNUM 80 #ifndef INADDR_NONE #define INADDR_NONE 0xffffffff #endif -static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream) +static size_t write_cb(void *ptr, size_t size, size_t nmemb, void *stream) { size_t written = fwrite(ptr, size, nmemb, (FILE *)stream); return written; @@ -99,13 +99,13 @@ static int sockopt_callback(void *clientp, curl_socket_t curlfd, int main(void) { CURL *curl; - CURLcode res; + CURLcode result; struct sockaddr_in servaddr; /* socket address structure */ curl_socket_t sockfd; - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -124,7 +124,7 @@ int main(void) memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; - servaddr.sin_port = htons(PORTNUM); + servaddr.sin_port = htons(PORTNUM); servaddr.sin_addr.s_addr = inet_addr(IPADDR); if(INADDR_NONE == servaddr.sin_addr.s_addr) { @@ -132,8 +132,7 @@ int main(void) return 2; } - if(connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) == - -1) { + if(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) { close(sockfd); printf("client error: connect: %s\n", strerror(errno)); return 1; @@ -143,7 +142,7 @@ int main(void) curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L); /* send all data to this function */ - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); /* call this function to get a socket */ curl_easy_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, opensocket); @@ -158,14 +157,14 @@ int main(void) curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); close(sockfd); - if(res) { - printf("libcurl error: %d\n", res); + if(result) { + printf("libcurl error: %d\n", result); return 4; } } diff --git a/docs/examples/fileupload.c b/docs/examples/fileupload.c index f827c68390a7..82ebd878c753 100644 --- a/docs/examples/fileupload.c +++ b/docs/examples/fileupload.c @@ -25,30 +25,37 @@ * Upload to a file:// URL * */ +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* for fopen() */ +#endif +#endif + #include -#include -#include #include +#include + +#include #ifdef _WIN32 #undef stat -#define stat _stat +#define stat _stati64 #undef fstat -#define fstat _fstat +#define fstat _fstati64 #define fileno _fileno #endif int main(void) { CURL *curl; - CURLcode res; + CURLcode result; struct stat file_info; curl_off_t speed_upload, total_time; FILE *fd; - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; fd = fopen("debugit", "rb"); /* open file to upload */ if(!fd) { @@ -57,12 +64,7 @@ int main(void) } /* to get the file size */ -#ifdef UNDER_CE - /* !checksrc! disable BANNEDFUNC 1 */ - if(stat("debugit", &file_info) != 0) { -#else if(fstat(fileno(fd), &file_info) != 0) { -#endif fclose(fd); curl_global_cleanup(); return 1; /* cannot continue */ @@ -87,21 +89,23 @@ int main(void) /* enable verbose for easier tracing */ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) { + if(result != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); } else { /* now extract transfer info */ curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD_T, &speed_upload); curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME_T, &total_time); - fprintf(stderr, "Speed: %lu bytes/sec during %lu.%06lu seconds\n", - (unsigned long)speed_upload, - (unsigned long)(total_time / 1000000), - (unsigned long)(total_time % 1000000)); + fprintf(stderr, "Speed: %" CURL_FORMAT_CURL_OFF_T " bytes/sec during " + "%" CURL_FORMAT_CURL_OFF_T + ".%06" CURL_FORMAT_CURL_OFF_T " seconds\n", + speed_upload, + total_time / 1000000, + total_time % 1000000); } /* always cleanup */ curl_easy_cleanup(curl); diff --git a/docs/examples/ftp-delete.c b/docs/examples/ftp-delete.c index f5c553ff68ef..6f670533c591 100644 --- a/docs/examples/ftp-delete.c +++ b/docs/examples/ftp-delete.c @@ -21,16 +21,15 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ -#include - -#include - /* * Delete a single file from an FTP server. * */ +#include + +#include -static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream) +static size_t write_cb(void *buffer, size_t size, size_t nmemb, void *stream) { (void)buffer; (void)stream; @@ -40,12 +39,12 @@ static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream) int main(void) { CURL *curl; - CURLcode res; + CURLcode result; struct curl_slist *headerlist = NULL; - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -54,7 +53,7 @@ int main(void) */ curl_easy_setopt(curl, CURLOPT_URL, "ftp://ftp.example.com/"); /* Define our callback to get called when there is data to be written */ - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); /* Switch on full protocol/debug output */ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); @@ -65,7 +64,7 @@ int main(void) /* pass in list of FTP commands to run after the transfer */ curl_easy_setopt(curl, CURLOPT_POSTQUOTE, headerlist); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* always cleanup */ curl_easy_cleanup(curl); @@ -73,13 +72,13 @@ int main(void) /* clean up the FTP commands list */ curl_slist_free_all(headerlist); - if(CURLE_OK != res) { + if(CURLE_OK != result) { /* we failed */ - fprintf(stderr, "curl told us %d\n", res); + fprintf(stderr, "curl told us %d\n", result); } } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/ftp-wildcard.c b/docs/examples/ftp-wildcard.c index 0861f2f0487e..cba40d6eb8ac 100644 --- a/docs/examples/ftp-wildcard.c +++ b/docs/examples/ftp-wildcard.c @@ -25,9 +25,16 @@ * FTP wildcard pattern matching * */ -#include +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* for fopen() */ +#endif +#endif + #include +#include + struct callback_data { FILE *output; }; @@ -78,8 +85,7 @@ static long file_is_downloaded(void *input) return CURL_CHUNK_END_FUNC_OK; } -static size_t write_it(char *buff, size_t size, size_t nmemb, - void *cb_data) +static size_t write_cb(char *buff, size_t size, size_t nmemb, void *cb_data) { struct callback_data *data = cb_data; size_t written = 0; @@ -94,51 +100,51 @@ static size_t write_it(char *buff, size_t size, size_t nmemb, int main(int argc, char **argv) { /* curl easy handle */ - CURL *handle; + CURL *curl; /* help data */ struct callback_data data = { 0 }; /* global initialization */ - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; /* initialization of easy handle */ - handle = curl_easy_init(); - if(!handle) { + curl = curl_easy_init(); + if(!curl) { curl_global_cleanup(); return CURLE_OUT_OF_MEMORY; } /* turn on wildcard matching */ - curl_easy_setopt(handle, CURLOPT_WILDCARDMATCH, 1L); + curl_easy_setopt(curl, CURLOPT_WILDCARDMATCH, 1L); /* callback is called before download of concrete file started */ - curl_easy_setopt(handle, CURLOPT_CHUNK_BGN_FUNCTION, file_is_coming); + curl_easy_setopt(curl, 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); + curl_easy_setopt(curl, CURLOPT_CHUNK_END_FUNCTION, file_is_downloaded); /* this callback writes contents into files */ - curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, write_it); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); /* put transfer data into callbacks */ - curl_easy_setopt(handle, CURLOPT_CHUNK_DATA, &data); - curl_easy_setopt(handle, CURLOPT_WRITEDATA, &data); + curl_easy_setopt(curl, CURLOPT_CHUNK_DATA, &data); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data); - /* curl_easy_setopt(handle, CURLOPT_VERBOSE, 1L); */ + /* curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); */ /* set a URL containing wildcard pattern (only in the last part) */ if(argc == 2) - curl_easy_setopt(handle, CURLOPT_URL, argv[1]); + curl_easy_setopt(curl, CURLOPT_URL, argv[1]); else - curl_easy_setopt(handle, CURLOPT_URL, "ftp://example.com/test/*"); + curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/test/*"); /* and start transfer! */ - res = curl_easy_perform(handle); + result = curl_easy_perform(curl); - curl_easy_cleanup(handle); + curl_easy_cleanup(curl); curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/ftpget.c b/docs/examples/ftpget.c index f4ba1e52aa24..e48edc9d5758 100644 --- a/docs/examples/ftpget.c +++ b/docs/examples/ftpget.c @@ -21,21 +21,26 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ -#include - -#include - /* * Get a single file from an FTP server. * */ +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* for fopen() */ +#endif +#endif + +#include + +#include struct FtpFile { const char *filename; FILE *stream; }; -static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream) +static size_t write_cb(void *buffer, size_t size, size_t nmemb, void *stream) { struct FtpFile *out = (struct FtpFile *)stream; if(!out->stream) { @@ -47,19 +52,18 @@ static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, void *stream) return fwrite(buffer, size, nmemb, out->stream); } - int main(void) { CURL *curl; - CURLcode res; + CURLcode result; struct FtpFile ftpfile = { "curl.tar.gz", /* name to store the file as if successful */ NULL }; - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -69,21 +73,21 @@ int main(void) curl_easy_setopt(curl, CURLOPT_URL, "ftp://ftp.example.com/curl/curl-7.9.2.tar.gz"); /* Define our callback to get called when there is data to be written */ - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); /* Set a pointer to our struct to pass to the callback */ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile); /* Switch on full protocol/debug output */ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* always cleanup */ curl_easy_cleanup(curl); - if(CURLE_OK != res) { + if(CURLE_OK != result) { /* we failed */ - fprintf(stderr, "curl told us %d\n", res); + fprintf(stderr, "curl told us %d\n", result); } } @@ -92,5 +96,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/ftpgetinfo.c b/docs/examples/ftpgetinfo.c index 549d3003a8a3..82861c21a839 100644 --- a/docs/examples/ftpgetinfo.c +++ b/docs/examples/ftpgetinfo.c @@ -21,15 +21,20 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ -#include -#include - -#include - /* * Checks a single file's size and mtime from an FTP server. * */ +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* for ctime(), fopen() */ +#endif +#endif + +#include +#include + +#include static size_t throw_away(void *ptr, size_t size, size_t nmemb, void *data) { @@ -44,14 +49,14 @@ int main(void) { char ftpurl[] = "ftp://ftp.example.com/gnu/binutils/binutils-2.19.1.tar.bz2"; CURL *curl; - CURLcode res; + CURLcode result; long filetime = -1; curl_off_t filesize = 0; const char *filename = strrchr(ftpurl, '/') + 1; - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -65,24 +70,24 @@ int main(void) /* Switch on full protocol/debug output */ /* curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(CURLE_OK == res) { + if(CURLE_OK == result) { /* https://curl.se/libcurl/c/curl_easy_getinfo.html */ - res = curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime); - if((CURLE_OK == res) && (filetime >= 0)) { + result = curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime); + if((CURLE_OK == result) && (filetime >= 0)) { time_t file_time = (time_t)filetime; printf("filetime %s: %s", filename, ctime(&file_time)); } - res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, - &filesize); - if((CURLE_OK == res) && (filesize > 0)) + result = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, + &filesize); + if((CURLE_OK == result) && (filesize > 0)) printf("filesize %s: %" CURL_FORMAT_CURL_OFF_T " bytes\n", filename, filesize); } else { /* we failed */ - fprintf(stderr, "curl told us %d\n", res); + fprintf(stderr, "curl told us %d\n", result); } /* always cleanup */ @@ -91,5 +96,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/ftpgetresp.c b/docs/examples/ftpgetresp.c index 6dce4ab7496a..c05f989f9a9d 100644 --- a/docs/examples/ftpgetresp.c +++ b/docs/examples/ftpgetresp.c @@ -21,34 +21,40 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ -#include - -#include - /* * Similar to ftpget.c but also stores the received response-lines * in a separate file using our own callback! * */ +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* for fopen() */ +#endif +#endif + +#include + +#include + static size_t write_response(void *ptr, size_t size, size_t nmemb, void *data) { FILE *writehere = (FILE *)data; return fwrite(ptr, size, nmemb, writehere); } -#define FTPBODY "ftp-list" +#define FTPBODY "ftp-list" #define FTPHEADERS "ftp-responses" int main(void) { CURL *curl; - CURLcode res; + CURLcode result; FILE *ftpfile; FILE *respfile; - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; /* local filename to store the file as */ ftpfile = fopen(FTPBODY, "wb"); /* b is binary, needed on Windows */ @@ -74,20 +80,20 @@ int main(void) CURLOPT_WRITEFUNCTION as well */ curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, write_response); curl_easy_setopt(curl, CURLOPT_HEADERDATA, respfile); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); } - fclose(ftpfile); /* close the local file */ + fclose(ftpfile); /* close the local file */ fclose(respfile); /* close the response file */ curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/ftpsget.c b/docs/examples/ftpsget.c index c2aee89c8487..fc56bb4ca209 100644 --- a/docs/examples/ftpsget.c +++ b/docs/examples/ftpsget.c @@ -21,23 +21,26 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - -#include - -#include - /* * Get a single file from an FTPS server. * */ +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* for fopen() */ +#endif +#endif + +#include + +#include struct FtpFile { const char *filename; FILE *stream; }; -static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, - void *stream) +static size_t write_cb(void *buffer, size_t size, size_t nmemb, void *stream) { struct FtpFile *out = (struct FtpFile *)stream; if(!out->stream) { @@ -49,19 +52,18 @@ static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, return fwrite(buffer, size, nmemb, out->stream); } - int main(void) { CURL *curl; - CURLcode res; + CURLcode result; struct FtpFile ftpfile = { "yourfile.bin", /* name to store the file as if successful */ NULL }; - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -73,7 +75,7 @@ int main(void) curl_easy_setopt(curl, CURLOPT_URL, "ftp://user@server/home/user/file.txt"); /* Define our callback to get called when there is data to be written */ - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); /* Set a pointer to our struct to pass to the callback */ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile); @@ -83,14 +85,14 @@ int main(void) /* Switch on full protocol/debug output */ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* always cleanup */ curl_easy_cleanup(curl); - if(CURLE_OK != res) { + if(CURLE_OK != result) { /* we failed */ - fprintf(stderr, "curl told us %d\n", res); + fprintf(stderr, "curl told us %d\n", result); } } @@ -99,5 +101,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/ftpupload.c b/docs/examples/ftpupload.c index 2bfb51f66e7c..85b68da1bf74 100644 --- a/docs/examples/ftpupload.c +++ b/docs/examples/ftpupload.c @@ -21,45 +21,47 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ +/* + * Performs an FTP upload and renames the file just after a successful + * transfer. + * + */ +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* for fopen(), strerror() */ +#endif +#endif + #include #include +#include +#include +#include +#include #include -#include -#include -#include -#ifdef UNDER_CE -#define strerror(e) "?" -#else -#include -#endif + #ifdef _WIN32 #include #undef stat -#define stat _stat +#define stat _stati64 #undef fstat -#define fstat _fstat +#define fstat _fstati64 #define fileno _fileno #else #include #endif -/* - * Performs an FTP upload and renames the file just after a successful - * transfer. - * - */ - -#define LOCAL_FILE "/tmp/uploadthis.txt" -#define UPLOAD_FILE_AS "while-uploading.txt" -#define REMOTE_URL "ftp://example.com/" UPLOAD_FILE_AS -#define RENAME_FILE_TO "renamed-and-fine.txt" +#define LOCAL_FILE "/tmp/uploadthis.txt" +#define UPLOAD_FILE_AS "while-uploading.txt" +#define REMOTE_URL "ftp://example.com/" UPLOAD_FILE_AS +#define RENAME_FILE_TO "renamed-and-fine.txt" /* NOTE: if you want this example to work on Windows with libcurl as a DLL, you MUST also provide a read callback with CURLOPT_READFUNCTION. Failing to do so might give you a crash since a DLL may not use the variable's memory when passed in to it from an app like this. */ -static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream) +static size_t read_cb(char *ptr, size_t size, size_t nmemb, void *stream) { unsigned long nread; /* in real-world cases, this would probably get this data differently @@ -78,7 +80,7 @@ static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream) int main(void) { CURL *curl; - CURLcode res; + CURLcode result; FILE *hd_src; struct stat file_info; curl_off_t fsize; @@ -90,29 +92,24 @@ int main(void) /* get a FILE * of the file */ hd_src = fopen(LOCAL_FILE, "rb"); if(!hd_src) { - printf("Couldn't open '%s': %s\n", LOCAL_FILE, strerror(errno)); + printf("Could not open '%s': %s\n", LOCAL_FILE, strerror(errno)); return 2; } /* to get the file size */ -#ifdef UNDER_CE - /* !checksrc! disable BANNEDFUNC 1 */ - if(stat(LOCAL_FILE, &file_info) != 0) { -#else if(fstat(fileno(hd_src), &file_info) != 0) { -#endif fclose(hd_src); return 1; /* cannot continue */ } fsize = file_info.st_size; - printf("Local file size: %lu bytes.\n", (unsigned long)fsize); + printf("Local file size: %" CURL_FORMAT_CURL_OFF_T " bytes.\n", fsize); /* In Windows, this inits the Winsock stuff */ - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) { + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) { fclose(hd_src); - return (int)res; + return (int)result; } /* get a curl handle */ @@ -123,7 +120,7 @@ int main(void) headerlist = curl_slist_append(headerlist, buf_2); /* we want to use our own read function */ - curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback); + curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_cb); /* enable uploading */ curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); @@ -144,11 +141,11 @@ int main(void) curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, fsize); /* Now run off and do what you have been told! */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* clean up the FTP commands list */ curl_slist_free_all(headerlist); @@ -159,5 +156,5 @@ int main(void) fclose(hd_src); /* close the local file */ curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/ftpuploadfrommem.c b/docs/examples/ftpuploadfrommem.c index 70242376ae17..db06edcd9f17 100644 --- a/docs/examples/ftpuploadfrommem.c +++ b/docs/examples/ftpuploadfrommem.c @@ -27,9 +27,10 @@ */ #include #include + #include -static const char data[]= +static const char data[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " "___ rhoncus odio id venenatis volutpat. Vestibulum dapibus " "bibendum ullamcorper. Maecenas finibus elit augue, vel " @@ -45,10 +46,10 @@ struct WriteThis { size_t sizeleft; }; -static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp) +static size_t read_cb(char *ptr, size_t size, size_t nmemb, void *userp) { struct WriteThis *upload = (struct WriteThis *)userp; - size_t max = size*nmemb; + size_t max = size * nmemb; if(max < 1) return 0; @@ -63,13 +64,13 @@ static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp) return copylen; } - return 0; /* no more data left to deliver */ + return 0; /* no more data left to deliver */ } int main(void) { CURL *curl; - CURLcode res; + CURLcode result; struct WriteThis upload; @@ -77,11 +78,11 @@ int main(void) upload.sizeleft = strlen(data); /* In Windows, this inits the Winsock stuff */ - res = curl_global_init(CURL_GLOBAL_DEFAULT); + result = curl_global_init(CURL_GLOBAL_DEFAULT); /* Check for errors */ - if(res != CURLE_OK) { + if(result != CURLE_OK) { fprintf(stderr, "curl_global_init() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); return 1; } @@ -99,7 +100,7 @@ int main(void) curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); /* we want to use our own read function */ - curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback); + curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_cb); /* pointer to pass to our read function */ curl_easy_setopt(curl, CURLOPT_READDATA, &upload); @@ -111,16 +112,16 @@ int main(void) curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)upload.sizeleft); - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/ftpuploadresume.c b/docs/examples/ftpuploadresume.c index 13df8541a2d6..4908505ea16e 100644 --- a/docs/examples/ftpuploadresume.c +++ b/docs/examples/ftpuploadresume.c @@ -25,9 +25,15 @@ * Upload to FTP, resuming failed transfers. Active mode. * */ +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* for fopen(), sscanf() */ +#endif +#endif #include #include + #include /* parse headers for Content-Length */ @@ -39,13 +45,13 @@ static size_t getcontentlengthfunc(void *ptr, size_t size, size_t nmemb, r = sscanf(ptr, "Content-Length: %ld\n", &len); if(r == 1) - *((long *) stream) = len; + *((long *)stream) = len; return size * nmemb; } /* discard downloaded data */ -static size_t discardfunc(void *ptr, size_t size, size_t nmemb, void *stream) +static size_t write_cb(void *ptr, size_t size, size_t nmemb, void *stream) { (void)ptr; (void)stream; @@ -53,7 +59,7 @@ static size_t discardfunc(void *ptr, size_t size, size_t nmemb, void *stream) } /* read data to upload */ -static size_t readfunc(char *ptr, size_t size, size_t nmemb, void *stream) +static size_t read_cb(char *ptr, size_t size, size_t nmemb, void *stream) { FILE *f = stream; size_t n; @@ -66,49 +72,46 @@ static size_t readfunc(char *ptr, size_t size, size_t nmemb, void *stream) return n; } - -static int upload(CURL *curlhandle, const char *remotepath, +static int upload(CURL *curl, const char *remotepath, const char *localpath, long timeout, long tries) { FILE *f; long uploaded_len = 0; - CURLcode r = CURLE_GOT_NOTHING; + CURLcode result = CURLE_GOT_NOTHING; int c; f = fopen(localpath, "rb"); if(!f) { -#ifndef UNDER_CE perror(NULL); -#endif return 0; } - curl_easy_setopt(curlhandle, CURLOPT_UPLOAD, 1L); + curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); - curl_easy_setopt(curlhandle, CURLOPT_URL, remotepath); + curl_easy_setopt(curl, CURLOPT_URL, remotepath); if(timeout) - curl_easy_setopt(curlhandle, CURLOPT_SERVER_RESPONSE_TIMEOUT, timeout); + curl_easy_setopt(curl, CURLOPT_SERVER_RESPONSE_TIMEOUT, timeout); - curl_easy_setopt(curlhandle, CURLOPT_HEADERFUNCTION, getcontentlengthfunc); - curl_easy_setopt(curlhandle, CURLOPT_HEADERDATA, &uploaded_len); + curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, getcontentlengthfunc); + curl_easy_setopt(curl, CURLOPT_HEADERDATA, &uploaded_len); - curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, discardfunc); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); - curl_easy_setopt(curlhandle, CURLOPT_READFUNCTION, readfunc); - curl_easy_setopt(curlhandle, CURLOPT_READDATA, f); + curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_cb); + curl_easy_setopt(curl, CURLOPT_READDATA, f); /* enable active mode */ - curl_easy_setopt(curlhandle, CURLOPT_FTPPORT, "-"); + curl_easy_setopt(curl, CURLOPT_FTPPORT, "-"); /* allow the server no more than 7 seconds to connect back */ - curl_easy_setopt(curlhandle, CURLOPT_ACCEPTTIMEOUT_MS, 7000L); + curl_easy_setopt(curl, CURLOPT_ACCEPTTIMEOUT_MS, 7000L); - curl_easy_setopt(curlhandle, CURLOPT_FTP_CREATE_MISSING_DIRS, 1L); + curl_easy_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS, 1L); - curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, 1L); + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); - for(c = 0; (r != CURLE_OK) && (c < tries); c++) { + for(c = 0; (result != CURLE_OK) && (c < tries); c++) { /* are we resuming? */ if(c) { /* yes */ /* determine the length of the file already written */ @@ -116,55 +119,52 @@ static int upload(CURL *curlhandle, const char *remotepath, /* * With NOBODY and NOHEADER, libcurl issues a SIZE command, but the only * way to retrieve the result is to parse the returned Content-Length - * header. Thus, getcontentlengthfunc(). We need discardfunc() above + * header. Thus, getcontentlengthfunc(). We need write_cb() above * because HEADER dumps the headers to stdout without it. */ - curl_easy_setopt(curlhandle, CURLOPT_NOBODY, 1L); - curl_easy_setopt(curlhandle, CURLOPT_HEADER, 1L); + curl_easy_setopt(curl, CURLOPT_NOBODY, 1L); + curl_easy_setopt(curl, CURLOPT_HEADER, 1L); - r = curl_easy_perform(curlhandle); - if(r != CURLE_OK) + result = curl_easy_perform(curl); + if(result != CURLE_OK) continue; - curl_easy_setopt(curlhandle, CURLOPT_NOBODY, 0L); - curl_easy_setopt(curlhandle, CURLOPT_HEADER, 0L); + curl_easy_setopt(curl, CURLOPT_NOBODY, 0L); + curl_easy_setopt(curl, CURLOPT_HEADER, 0L); fseek(f, uploaded_len, SEEK_SET); - curl_easy_setopt(curlhandle, CURLOPT_APPEND, 1L); + curl_easy_setopt(curl, CURLOPT_APPEND, 1L); } else { /* no */ - curl_easy_setopt(curlhandle, CURLOPT_APPEND, 0L); + curl_easy_setopt(curl, CURLOPT_APPEND, 0L); } - r = curl_easy_perform(curlhandle); + result = curl_easy_perform(curl); } fclose(f); - if(r == CURLE_OK) + if(result == CURLE_OK) return 1; else { - fprintf(stderr, "%s\n", curl_easy_strerror(r)); + fprintf(stderr, "%s\n", curl_easy_strerror(result)); return 0; } } int main(void) { - CURL *curlhandle = NULL; - - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; - - curlhandle = curl_easy_init(); - if(curlhandle) { + CURL *curl = NULL; - upload(curlhandle, "ftp://user:pass@example.com/path/file", "C:\\file", - 0, 3); + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; - curl_easy_cleanup(curlhandle); + curl = curl_easy_init(); + if(curl) { + upload(curl, "ftp://user:pass@example.com/path/file", "C:\\file", 0, 3); + curl_easy_cleanup(curl); } curl_global_cleanup(); diff --git a/docs/examples/getinfo.c b/docs/examples/getinfo.c index d6257afa791c..66bb69b8ae5b 100644 --- a/docs/examples/getinfo.c +++ b/docs/examples/getinfo.c @@ -26,27 +26,28 @@ * */ #include + #include int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(CURLE_OK == res) { + if(CURLE_OK == result) { char *ct; /* ask for the content-type */ - res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct); + result = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct); - if((CURLE_OK == res) && ct) + if((CURLE_OK == result) && ct) printf("We received Content-Type: %s\n", ct); } @@ -54,5 +55,5 @@ int main(void) curl_easy_cleanup(curl); } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/getinmemory.c b/docs/examples/getinmemory.c index aa31654c168a..ea4da5dd9d0f 100644 --- a/docs/examples/getinmemory.c +++ b/docs/examples/getinmemory.c @@ -26,7 +26,6 @@ * chunk of memory instead of storing it in a file. * */ - #include #include #include @@ -38,8 +37,7 @@ struct MemoryStruct { size_t size; }; -static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, - void *userp) +static size_t write_cb(void *contents, size_t size, size_t nmemb, void *userp) { size_t realsize = size * nmemb; struct MemoryStruct *mem = (struct MemoryStruct *)userp; @@ -61,42 +59,42 @@ static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, int main(void) { - CURL *curl_handle; - CURLcode res; + CURL *curl; + CURLcode result; struct MemoryStruct chunk; - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; - chunk.memory = malloc(1); /* grown as needed by the realloc above */ - chunk.size = 0; /* no data at this point */ + chunk.memory = malloc(1); /* grown as needed by the realloc above */ + chunk.size = 0; /* no data at this point */ /* init the curl session */ - curl_handle = curl_easy_init(); - if(curl_handle) { + curl = curl_easy_init(); + if(curl) { /* specify URL to get */ - curl_easy_setopt(curl_handle, CURLOPT_URL, "https://www.example.com/"); + curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/"); /* send all data to this function */ - curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); /* we pass our 'chunk' struct to the callback function */ - curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); /* some servers do not like requests that are made without a user-agent field, so we provide one */ - curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); + curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0"); /* get it! */ - res = curl_easy_perform(curl_handle); + result = curl_easy_perform(curl); /* check for errors */ - if(res != CURLE_OK) { + if(result != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); } else { /* @@ -110,7 +108,7 @@ int main(void) } /* cleanup curl stuff */ - curl_easy_cleanup(curl_handle); + curl_easy_cleanup(curl); } free(chunk.memory); @@ -118,5 +116,5 @@ int main(void) /* we are done with libcurl, so clean it up */ curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/getredirect.c b/docs/examples/getredirect.c index 908cd5f850f8..fabfc594bc5e 100644 --- a/docs/examples/getredirect.c +++ b/docs/examples/getredirect.c @@ -26,18 +26,19 @@ * */ #include + #include int main(void) { CURL *curl; - CURLcode res; + CURLcode result; char *location; long response_code; - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -45,23 +46,22 @@ int main(void) /* example.com is redirected, figure out the redirection! */ - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); else { - res = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); - if((res == CURLE_OK) && - ((response_code / 100) != 3)) { + result = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); + if((result == CURLE_OK) && ((response_code / 100) != 3)) { /* a redirect implies a 3xx response code */ fprintf(stderr, "Not a redirect.\n"); } else { - res = curl_easy_getinfo(curl, CURLINFO_REDIRECT_URL, &location); + result = curl_easy_getinfo(curl, CURLINFO_REDIRECT_URL, &location); - if((res == CURLE_OK) && location) { + if((result == CURLE_OK) && location) { /* This is the new absolute URL that you could redirect to, even if * the Location: response header may have been a relative URL. */ printf("Redirected to: %s\n", location); @@ -73,5 +73,5 @@ int main(void) curl_easy_cleanup(curl); } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/getreferrer.c b/docs/examples/getreferrer.c index ae42f4605fce..ac190f3fa1d5 100644 --- a/docs/examples/getreferrer.c +++ b/docs/examples/getreferrer.c @@ -26,31 +26,32 @@ * */ #include + #include int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); curl_easy_setopt(curl, CURLOPT_REFERER, "https://example.org/referrer"); - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); else { char *hdr; - res = curl_easy_getinfo(curl, CURLINFO_REFERER, &hdr); - if((res == CURLE_OK) && hdr) + result = curl_easy_getinfo(curl, CURLINFO_REFERER, &hdr); + if((result == CURLE_OK) && hdr) printf("Referrer header: %s\n", hdr); } diff --git a/docs/examples/ghiper.c b/docs/examples/ghiper.c index e9844fc89e01..20a8a2de2d2f 100644 --- a/docs/examples/ghiper.c +++ b/docs/examples/ghiper.c @@ -41,7 +41,6 @@ of URL's and creates some new easy handles to fetch each URL via the curl_multi "hiper" API. - Thus, you can try a single URL: % echo http://www.yahoo.com > hiper.fifo @@ -55,19 +54,20 @@ callback. */ - #include -#include + #include #include #include #include #include +#include + #include -#define MSG_OUT g_print /* Change to "g_error" to write to stderr */ -#define SHOW_VERBOSE 0L /* Set to non-zero for libcurl messages */ -#define SHOW_PROGRESS 0 /* Set to non-zero to enable progress callback */ +#define MSG_OUT g_print /* Change to "g_error" to write to stderr */ +#define SHOW_VERBOSE 0L /* Set to non-zero for libcurl messages */ +#define SHOW_PROGRESS 0 /* Set to non-zero to enable progress callback */ /* Global information, common to all connections */ struct GlobalInfo { @@ -78,7 +78,7 @@ struct GlobalInfo { /* Information associated with a specific easy handle */ struct ConnInfo { - CURL *easy; + CURL *curl; char *url; struct GlobalInfo *global; char error[CURL_ERROR_SIZE]; @@ -87,7 +87,7 @@ struct ConnInfo { /* Information associated with a specific socket */ struct SockInfo { curl_socket_t sockfd; - CURL *easy; + CURL *curl; int action; long timeout; GIOChannel *ch; @@ -101,14 +101,27 @@ static void mcode_or_die(const char *where, CURLMcode code) if(CURLM_OK != code) { const char *s; switch(code) { - case CURLM_BAD_HANDLE: s = "CURLM_BAD_HANDLE"; break; - case CURLM_BAD_EASY_HANDLE: s = "CURLM_BAD_EASY_HANDLE"; break; - case CURLM_OUT_OF_MEMORY: s = "CURLM_OUT_OF_MEMORY"; break; - case CURLM_INTERNAL_ERROR: s = "CURLM_INTERNAL_ERROR"; break; - case CURLM_BAD_SOCKET: s = "CURLM_BAD_SOCKET"; break; - case CURLM_UNKNOWN_OPTION: s = "CURLM_UNKNOWN_OPTION"; break; - case CURLM_LAST: s = "CURLM_LAST"; break; - default: s = "CURLM_unknown"; + case CURLM_BAD_HANDLE: + s = "CURLM_BAD_HANDLE"; + break; + case CURLM_BAD_EASY_HANDLE: + s = "CURLM_BAD_EASY_HANDLE"; + break; + case CURLM_OUT_OF_MEMORY: + s = "CURLM_OUT_OF_MEMORY"; + break; + case CURLM_INTERNAL_ERROR: + s = "CURLM_INTERNAL_ERROR"; + break; + case CURLM_BAD_SOCKET: + s = "CURLM_BAD_SOCKET"; + break; + case CURLM_UNKNOWN_OPTION: + s = "CURLM_UNKNOWN_OPTION"; + break; + default: + s = "CURLM_unknown"; + break; } MSG_OUT("ERROR: %s returns %s\n", where, s); exit(code); @@ -124,16 +137,16 @@ static void check_multi_info(struct GlobalInfo *g) MSG_OUT("REMAINING: %d\n", g->still_running); while((msg = curl_multi_info_read(g->multi, &msgs_left))) { if(msg->msg == CURLMSG_DONE) { - CURL *easy = msg->easy_handle; - CURLcode res = msg->data.result; + CURL *curl = msg->easy_handle; + CURLcode result = msg->data.result; char *eff_url; struct ConnInfo *conn; - curl_easy_getinfo(easy, CURLINFO_PRIVATE, &conn); - curl_easy_getinfo(easy, CURLINFO_EFFECTIVE_URL, &eff_url); - MSG_OUT("DONE: %s => (%d) %s\n", eff_url, res, conn->error); - curl_multi_remove_handle(g->multi, easy); + curl_easy_getinfo(curl, CURLINFO_PRIVATE, &conn); + curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &eff_url); + MSG_OUT("DONE: %s => (%d) %s\n", eff_url, result, conn->error); + curl_multi_remove_handle(g->multi, curl); free(conn->url); - curl_easy_cleanup(easy); + curl_easy_cleanup(curl); free(conn); } } @@ -143,11 +156,11 @@ static void check_multi_info(struct GlobalInfo *g) static gboolean timer_cb(gpointer data) { struct GlobalInfo *g = (struct GlobalInfo *)data; - CURLMcode rc; + CURLMcode mresult; - rc = curl_multi_socket_action(g->multi, + mresult = curl_multi_socket_action(g->multi, CURL_SOCKET_TIMEOUT, 0, &g->still_running); - mcode_or_die("timer_cb: curl_multi_socket_action", rc); + mcode_or_die("timer_cb: curl_multi_socket_action", mresult); check_multi_info(g); return FALSE; } @@ -157,8 +170,8 @@ static int update_timeout_cb(CURLM *multi, long timeout_ms, void *userp) { struct timeval timeout; struct GlobalInfo *g = (struct GlobalInfo *)userp; - timeout.tv_sec = timeout_ms/1000; - timeout.tv_usec = (timeout_ms%1000)*1000; + timeout.tv_sec = timeout_ms / 1000; + timeout.tv_usec = (timeout_ms % 1000) * 1000; MSG_OUT("*** update_timeout_cb %ld => %ld:%ld ***\n", timeout_ms, timeout.tv_sec, timeout.tv_usec); @@ -177,16 +190,16 @@ static int update_timeout_cb(CURLM *multi, long timeout_ms, void *userp) /* Called by glib when we get action on a multi socket */ static gboolean event_cb(GIOChannel *ch, GIOCondition condition, gpointer data) { - struct GlobalInfo *g = (struct GlobalInfo*) data; - CURLMcode rc; + struct GlobalInfo *g = (struct GlobalInfo *)data; + CURLMcode mresult; int fd = g_io_channel_unix_get_fd(ch); int action = ((condition & G_IO_IN) ? CURL_CSELECT_IN : 0) | ((condition & G_IO_OUT) ? CURL_CSELECT_OUT : 0); - rc = curl_multi_socket_action(g->multi, fd, action, &g->still_running); - mcode_or_die("event_cb: curl_multi_socket_action", rc); + mresult = curl_multi_socket_action(g->multi, fd, action, &g->still_running); + mcode_or_die("event_cb: curl_multi_socket_action", mresult); check_multi_info(g); if(g->still_running) { @@ -223,7 +236,7 @@ static void setsock(struct SockInfo *f, curl_socket_t s, CURL *e, int act, f->sockfd = s; f->action = act; - f->easy = e; + f->curl = e; if(f->ev) { g_source_remove(f->ev); } @@ -231,23 +244,23 @@ static void setsock(struct SockInfo *f, curl_socket_t s, CURL *e, int act, } /* Initialize a new SockInfo structure */ -static void addsock(curl_socket_t s, CURL *easy, int action, +static void addsock(curl_socket_t s, CURL *curl, int action, struct GlobalInfo *g) { struct SockInfo *fdp = g_malloc0(sizeof(struct SockInfo)); fdp->global = g; fdp->ch = g_io_channel_unix_new(s); - setsock(fdp, s, easy, action, g); + setsock(fdp, s, curl, action, g); curl_multi_assign(g->multi, s, fdp); } /* CURLMOPT_SOCKETFUNCTION */ static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp) { - struct GlobalInfo *g = (struct GlobalInfo*) cbp; - struct SockInfo *fdp = (struct SockInfo*) sockp; - static const char *whatstr[]={ "none", "IN", "OUT", "INOUT", "REMOVE" }; + struct GlobalInfo *g = (struct GlobalInfo *)cbp; + struct SockInfo *fdp = (struct SockInfo *)sockp; + static const char *whatstr[] = { "none", "IN", "OUT", "INOUT", "REMOVE" }; MSG_OUT("socket callback: s=%d e=%p what=%s ", s, e, whatstr[what]); if(what == CURL_POLL_REMOVE) { @@ -262,8 +275,7 @@ static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp) addsock(s, e, what, g); } else { - MSG_OUT( - "Changing action from %d to %d\n", fdp->action, what); + MSG_OUT("Changing action from %d to %d\n", fdp->action, what); setsock(fdp, s, e, what, g); } } @@ -274,7 +286,7 @@ static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp) static size_t write_cb(void *ptr, size_t size, size_t nmemb, void *data) { size_t realsize = size * nmemb; - struct ConnInfo *conn = (struct ConnInfo*) data; + struct ConnInfo *conn = (struct ConnInfo *)data; (void)ptr; (void)conn; return realsize; @@ -288,8 +300,8 @@ static int xferinfo_cb(void *p, curl_off_t dltotal, curl_off_t dlnow, (void)ult; (void)uln; - fprintf(MSG_OUT, "Progress: %s (%" CURL_FORMAT_CURL_OFF_T - "/%" CURL_FORMAT_CURL_OFF_T ")\n", conn->url, dlnow, dltotal); + fprintf(MSG_OUT, "Progress: %s (%" CURL_FORMAT_CURL_OFF_T "/" + "%" CURL_FORMAT_CURL_OFF_T ")\n", conn->url, dlnow, dltotal); return 0; } @@ -297,34 +309,34 @@ static int xferinfo_cb(void *p, curl_off_t dltotal, curl_off_t dlnow, static void new_conn(const char *url, struct GlobalInfo *g) { struct ConnInfo *conn; - CURLMcode rc; + CURLMcode mresult; conn = g_malloc0(sizeof(*conn)); conn->error[0] = '\0'; - conn->easy = curl_easy_init(); - if(!conn->easy) { + conn->curl = curl_easy_init(); + if(!conn->curl) { MSG_OUT("curl_easy_init() failed, exiting!\n"); exit(2); } conn->global = g; conn->url = g_strdup(url); - curl_easy_setopt(conn->easy, CURLOPT_URL, conn->url); - curl_easy_setopt(conn->easy, CURLOPT_WRITEFUNCTION, write_cb); - curl_easy_setopt(conn->easy, CURLOPT_WRITEDATA, &conn); - curl_easy_setopt(conn->easy, CURLOPT_VERBOSE, SHOW_VERBOSE); - curl_easy_setopt(conn->easy, CURLOPT_ERRORBUFFER, conn->error); - curl_easy_setopt(conn->easy, CURLOPT_PRIVATE, conn); - curl_easy_setopt(conn->easy, CURLOPT_NOPROGRESS, SHOW_PROGRESS ? 0L : 1L); - curl_easy_setopt(conn->easy, CURLOPT_XFERINFOFUNCTION, xferinfo_cb); - curl_easy_setopt(conn->easy, CURLOPT_PROGRESSDATA, conn); - curl_easy_setopt(conn->easy, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt(conn->easy, CURLOPT_CONNECTTIMEOUT, 30L); - curl_easy_setopt(conn->easy, CURLOPT_LOW_SPEED_LIMIT, 1L); - curl_easy_setopt(conn->easy, CURLOPT_LOW_SPEED_TIME, 30L); - - MSG_OUT("Adding easy %p to multi %p (%s)\n", conn->easy, g->multi, url); - rc = curl_multi_add_handle(g->multi, conn->easy); - mcode_or_die("new_conn: curl_multi_add_handle", rc); + curl_easy_setopt(conn->curl, CURLOPT_URL, conn->url); + curl_easy_setopt(conn->curl, CURLOPT_WRITEFUNCTION, write_cb); + curl_easy_setopt(conn->curl, CURLOPT_WRITEDATA, &conn); + curl_easy_setopt(conn->curl, CURLOPT_VERBOSE, SHOW_VERBOSE); + curl_easy_setopt(conn->curl, CURLOPT_ERRORBUFFER, conn->error); + curl_easy_setopt(conn->curl, CURLOPT_PRIVATE, conn); + curl_easy_setopt(conn->curl, CURLOPT_NOPROGRESS, SHOW_PROGRESS ? 0L : 1L); + curl_easy_setopt(conn->curl, CURLOPT_XFERINFOFUNCTION, xferinfo_cb); + curl_easy_setopt(conn->curl, CURLOPT_PROGRESSDATA, conn); + curl_easy_setopt(conn->curl, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(conn->curl, CURLOPT_CONNECTTIMEOUT, 30L); + curl_easy_setopt(conn->curl, CURLOPT_LOW_SPEED_LIMIT, 1L); + curl_easy_setopt(conn->curl, CURLOPT_LOW_SPEED_TIME, 30L); + + MSG_OUT("Adding easy %p to multi %p (%s)\n", conn->curl, g->multi, url); + mresult = curl_multi_add_handle(g->multi, conn->curl); + mcode_or_die("new_conn: curl_multi_add_handle", mresult); /* note that add_handle() sets a timeout to trigger soon so that the necessary socket_action() gets called */ @@ -343,18 +355,18 @@ static gboolean fifo_cb(GIOChannel *ch, GIOCondition condition, gpointer data) rv = g_io_channel_read_line(ch, &buf, &len, &tp, &err); if(buf) { if(tp) { - buf[tp]='\0'; + buf[tp] = '\0'; } - new_conn(buf, (struct GlobalInfo*)data); + new_conn(buf, (struct GlobalInfo *)data); g_free(buf); } else { buf = g_malloc(BUF_SIZE + 1); while(TRUE) { - buf[BUF_SIZE]='\0'; + buf[BUF_SIZE] = '\0'; g_io_channel_read_chars(ch, buf, BUF_SIZE, &len, &err); if(len) { - buf[len]='\0'; + buf[len] = '\0'; if(all) { tmp = all; all = g_strdup_printf("%s%s", tmp, buf); @@ -369,7 +381,7 @@ static gboolean fifo_cb(GIOChannel *ch, GIOCondition condition, gpointer data) } } if(all) { - new_conn(all, (struct GlobalInfo*)data); + new_conn(all, (struct GlobalInfo *)data); g_free(all); } g_free(buf); @@ -417,13 +429,13 @@ int init_fifo(void) int main(void) { struct GlobalInfo *g = g_malloc0(sizeof(struct GlobalInfo)); - GMainLoop*gmain; + GMainLoop *gmain; int fd; - GIOChannel* ch; + GIOChannel *ch; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; fd = init_fifo(); if(fd == CURL_SOCKET_BAD) { diff --git a/docs/examples/headerapi.c b/docs/examples/headerapi.c index 428374bac667..cbc60acc94a2 100644 --- a/docs/examples/headerapi.c +++ b/docs/examples/headerapi.c @@ -26,6 +26,7 @@ * */ #include + #include static size_t write_cb(char *data, size_t n, size_t l, void *userp) @@ -33,16 +34,16 @@ static size_t write_cb(char *data, size_t n, size_t l, void *userp) /* take care of the data here, ignored in this example */ (void)data; (void)userp; - return n*l; + return n * l; } int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -54,12 +55,12 @@ int main(void) /* this example just ignores the content */ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); if(CURLHE_OK == curl_easy_header(curl, "Content-Type", 0, CURLH_HEADER, -1, &header)) @@ -75,7 +76,6 @@ int main(void) printf(" %s: %s (%u)\n", h->name, h->value, (unsigned int)h->amount); prev = h; } while(h); - } /* always cleanup */ curl_easy_cleanup(curl); diff --git a/docs/examples/hiperfifo.c b/docs/examples/hiperfifo.c index cc22e70abbe4..fc4c180582da 100644 --- a/docs/examples/hiperfifo.c +++ b/docs/examples/hiperfifo.c @@ -41,7 +41,6 @@ Whenever there is input into the fifo, the program reads the input as a list of URL's and creates some new easy handles to fetch each URL via the curl_multi "hiper" API. - Thus, you can try a single URL: % echo http://www.yahoo.com > hiper.fifo @@ -58,25 +57,25 @@ This is purely a demo app, all retrieved data is simply discarded by the write callback. */ - +#include +#include #include -#include #include +#include +#include +#include +#include #include #include #include -#include + #include + #include #include -#include -#include -#include -#include #define MSG_OUT stdout /* Send info to stdout, change to stderr if you want */ - /* Global information, common to all connections */ struct GlobalInfo { struct event_base *evbase; @@ -90,7 +89,7 @@ struct GlobalInfo { /* Information associated with a specific easy handle */ struct ConnInfo { - CURL *easy; + CURL *curl; char *url; struct GlobalInfo *global; char error[CURL_ERROR_SIZE]; @@ -99,30 +98,42 @@ struct ConnInfo { /* Information associated with a specific socket */ struct SockInfo { curl_socket_t sockfd; - CURL *easy; + CURL *curl; int action; long timeout; struct event ev; struct GlobalInfo *global; }; -#define mycase(code) \ - case code: s = __STRING(code) - /* Die if we get a bad CURLMcode somewhere */ static void mcode_or_die(const char *where, CURLMcode code) { if(CURLM_OK != code) { const char *s; switch(code) { - mycase(CURLM_BAD_HANDLE); break; - mycase(CURLM_BAD_EASY_HANDLE); break; - mycase(CURLM_OUT_OF_MEMORY); break; - mycase(CURLM_INTERNAL_ERROR); break; - mycase(CURLM_UNKNOWN_OPTION); break; - mycase(CURLM_LAST); break; - default: s = "CURLM_unknown"; break; - mycase(CURLM_BAD_SOCKET); + case CURLM_BAD_HANDLE: + s = "CURLM_BAD_HANDLE"; + break; + case CURLM_BAD_EASY_HANDLE: + s = "CURLM_BAD_EASY_HANDLE"; + break; + case CURLM_OUT_OF_MEMORY: + s = "CURLM_OUT_OF_MEMORY"; + break; + case CURLM_INTERNAL_ERROR: + s = "CURLM_INTERNAL_ERROR"; + break; + case CURLM_UNKNOWN_OPTION: + s = "CURLM_UNKNOWN_OPTION"; + break; + case CURLM_LAST: + s = "CURLM_LAST"; + break; + default: + s = "CURLM_unknown"; + break; + case CURLM_BAD_SOCKET: + s = "CURLM_BAD_SOCKET"; fprintf(MSG_OUT, "ERROR: %s returns %s\n", where, s); /* ignore this error */ return; @@ -138,8 +149,8 @@ static int multi_timer_cb(CURLM *multi, long timeout_ms, struct GlobalInfo *g) struct timeval timeout; (void)multi; - timeout.tv_sec = timeout_ms/1000; - timeout.tv_usec = (timeout_ms%1000)*1000; + timeout.tv_sec = timeout_ms / 1000; + timeout.tv_usec = (timeout_ms % 1000) * 1000; fprintf(MSG_OUT, "multi_timer_cb: Setting timeout to %ld ms\n", timeout_ms); /* @@ -162,20 +173,18 @@ static void check_multi_info(struct GlobalInfo *g) CURLMsg *msg; int msgs_left; struct ConnInfo *conn; - CURL *easy; - CURLcode res; fprintf(MSG_OUT, "REMAINING: %d\n", g->still_running); while((msg = curl_multi_info_read(g->multi, &msgs_left))) { if(msg->msg == CURLMSG_DONE) { - easy = msg->easy_handle; - res = msg->data.result; - curl_easy_getinfo(easy, CURLINFO_PRIVATE, &conn); - curl_easy_getinfo(easy, CURLINFO_EFFECTIVE_URL, &eff_url); - fprintf(MSG_OUT, "DONE: %s => (%d) %s\n", eff_url, res, conn->error); - curl_multi_remove_handle(g->multi, easy); + CURL *curl = msg->easy_handle; + CURLcode result = msg->data.result; + curl_easy_getinfo(curl, CURLINFO_PRIVATE, &conn); + curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &eff_url); + fprintf(MSG_OUT, "DONE: %s => (%d) %s\n", eff_url, result, conn->error); + curl_multi_remove_handle(g->multi, curl); free(conn->url); - curl_easy_cleanup(easy); + curl_easy_cleanup(curl); free(conn); } } @@ -186,15 +195,15 @@ static void check_multi_info(struct GlobalInfo *g) /* Called by libevent when we get action on a multi socket */ static void event_cb(int fd, short kind, void *userp) { - struct GlobalInfo *g = (struct GlobalInfo*) userp; - CURLMcode rc; + struct GlobalInfo *g = (struct GlobalInfo *)userp; + CURLMcode mresult; int action = ((kind & EV_READ) ? CURL_CSELECT_IN : 0) | ((kind & EV_WRITE) ? CURL_CSELECT_OUT : 0); - rc = curl_multi_socket_action(g->multi, fd, action, &g->still_running); - mcode_or_die("event_cb: curl_multi_socket_action", rc); + mresult = curl_multi_socket_action(g->multi, fd, action, &g->still_running); + mcode_or_die("event_cb: curl_multi_socket_action", mresult); check_multi_info(g); if(g->still_running <= 0) { @@ -209,13 +218,13 @@ static void event_cb(int fd, short kind, void *userp) static void timer_cb(int fd, short kind, void *userp) { struct GlobalInfo *g = (struct GlobalInfo *)userp; - CURLMcode rc; + CURLMcode mresult; (void)fd; (void)kind; - rc = curl_multi_socket_action(g->multi, + mresult = curl_multi_socket_action(g->multi, CURL_SOCKET_TIMEOUT, 0, &g->still_running); - mcode_or_die("timer_cb: curl_multi_socket_action", rc); + mcode_or_die("timer_cb: curl_multi_socket_action", mresult); check_multi_info(g); } @@ -240,7 +249,7 @@ static void setsock(struct SockInfo *f, curl_socket_t s, CURL *e, int act, f->sockfd = s; f->action = act; - f->easy = e; + f->curl = e; if(event_initialized(&f->ev)) { event_del(&f->ev); } @@ -249,25 +258,24 @@ static void setsock(struct SockInfo *f, curl_socket_t s, CURL *e, int act, } /* Initialize a new SockInfo structure */ -static void addsock(curl_socket_t s, CURL *easy, int action, +static void addsock(curl_socket_t s, CURL *curl, int action, struct GlobalInfo *g) { struct SockInfo *fdp = calloc(1, sizeof(struct SockInfo)); fdp->global = g; - setsock(fdp, s, easy, action, g); + setsock(fdp, s, curl, action, g); curl_multi_assign(g->multi, s, fdp); } /* CURLMOPT_SOCKETFUNCTION */ static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp) { - struct GlobalInfo *g = (struct GlobalInfo*) cbp; - struct SockInfo *fdp = (struct SockInfo*) sockp; - const char *whatstr[]={ "none", "IN", "OUT", "INOUT", "REMOVE" }; + struct GlobalInfo *g = (struct GlobalInfo *)cbp; + struct SockInfo *fdp = (struct SockInfo *)sockp; + const char *whatstr[] = { "none", "IN", "OUT", "INOUT", "REMOVE" }; - fprintf(MSG_OUT, - "socket callback: s=%d e=%p what=%s ", s, e, whatstr[what]); + fprintf(MSG_OUT, "socket callback: s=%d e=%p what=%s ", s, e, whatstr[what]); if(what == CURL_POLL_REMOVE) { fprintf(MSG_OUT, "\n"); remsock(fdp); @@ -278,8 +286,7 @@ static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp) addsock(s, e, what, g); } else { - fprintf(MSG_OUT, - "Changing action from %s to %s\n", + fprintf(MSG_OUT, "Changing action from %s to %s\n", whatstr[fdp->action], whatstr[what]); setsock(fdp, s, e, what, g); } @@ -303,8 +310,8 @@ static int xferinfo_cb(void *p, curl_off_t dltotal, curl_off_t dlnow, (void)ult; (void)uln; - fprintf(MSG_OUT, "Progress: %s (%" CURL_FORMAT_CURL_OFF_T - "/%" CURL_FORMAT_CURL_OFF_T ")\n", conn->url, dlnow, dltotal); + fprintf(MSG_OUT, "Progress: %s (%" CURL_FORMAT_CURL_OFF_T "/" + "%" CURL_FORMAT_CURL_OFF_T ")\n", conn->url, dlnow, dltotal); return 0; } @@ -312,32 +319,32 @@ static int xferinfo_cb(void *p, curl_off_t dltotal, curl_off_t dlnow, static void new_conn(const char *url, struct GlobalInfo *g) { struct ConnInfo *conn; - CURLMcode rc; + CURLMcode mresult; conn = calloc(1, sizeof(*conn)); conn->error[0] = '\0'; - conn->easy = curl_easy_init(); - if(!conn->easy) { + conn->curl = curl_easy_init(); + if(!conn->curl) { fprintf(MSG_OUT, "curl_easy_init() failed, exiting!\n"); exit(2); } conn->global = g; conn->url = strdup(url); - curl_easy_setopt(conn->easy, CURLOPT_URL, conn->url); - curl_easy_setopt(conn->easy, CURLOPT_WRITEFUNCTION, write_cb); - curl_easy_setopt(conn->easy, CURLOPT_WRITEDATA, conn); - curl_easy_setopt(conn->easy, CURLOPT_VERBOSE, 1L); - curl_easy_setopt(conn->easy, CURLOPT_ERRORBUFFER, conn->error); - curl_easy_setopt(conn->easy, CURLOPT_PRIVATE, conn); - curl_easy_setopt(conn->easy, CURLOPT_NOPROGRESS, 0L); - curl_easy_setopt(conn->easy, CURLOPT_XFERINFOFUNCTION, xferinfo_cb); - curl_easy_setopt(conn->easy, CURLOPT_PROGRESSDATA, conn); - curl_easy_setopt(conn->easy, CURLOPT_FOLLOWLOCATION, 1L); - fprintf(MSG_OUT, - "Adding easy %p to multi %p (%s)\n", conn->easy, g->multi, url); - rc = curl_multi_add_handle(g->multi, conn->easy); - mcode_or_die("new_conn: curl_multi_add_handle", rc); + curl_easy_setopt(conn->curl, CURLOPT_URL, conn->url); + curl_easy_setopt(conn->curl, CURLOPT_WRITEFUNCTION, write_cb); + curl_easy_setopt(conn->curl, CURLOPT_WRITEDATA, conn); + curl_easy_setopt(conn->curl, CURLOPT_VERBOSE, 1L); + curl_easy_setopt(conn->curl, CURLOPT_ERRORBUFFER, conn->error); + curl_easy_setopt(conn->curl, CURLOPT_PRIVATE, conn); + curl_easy_setopt(conn->curl, CURLOPT_NOPROGRESS, 0L); + curl_easy_setopt(conn->curl, CURLOPT_XFERINFOFUNCTION, xferinfo_cb); + curl_easy_setopt(conn->curl, CURLOPT_PROGRESSDATA, conn); + curl_easy_setopt(conn->curl, CURLOPT_FOLLOWLOCATION, 1L); + fprintf(MSG_OUT, "Adding easy %p to multi %p (%s)\n", + conn->curl, g->multi, url); + mresult = curl_multi_add_handle(g->multi, conn->curl); + mcode_or_die("new_conn: curl_multi_add_handle", mresult); /* note that the add_handle() sets a time-out to trigger soon so that the necessary socket_action() gets called */ @@ -354,9 +361,9 @@ static void fifo_cb(int fd, short event, void *arg) (void)event; do { - s[0]='\0'; + s[0] = '\0'; rv = fscanf(g->input, "%1023s%n", s, &n); - s[n]='\0'; + s[n] = '\0'; if(n && s[0]) { if(!strcmp(s, "stop")) { g->stopped = 1; @@ -387,7 +394,7 @@ static int init_fifo(struct GlobalInfo *g) } } unlink(fifo); - if(mkfifo (fifo, 0600) == -1) { + if(mkfifo(fifo, 0600) == -1) { perror("mkfifo"); return 1; } @@ -399,7 +406,7 @@ static int init_fifo(struct GlobalInfo *g) g->input = fdopen(sockfd, "r"); fprintf(MSG_OUT, "Now, pipe some URL's into > %s\n", fifo); - event_assign(&g->fifo_event, g->evbase, sockfd, EV_READ|EV_PERSIST, + event_assign(&g->fifo_event, g->evbase, sockfd, EV_READ | EV_PERSIST, fifo_cb, g); event_add(&g->fifo_event, NULL); return 0; @@ -407,21 +414,19 @@ static int init_fifo(struct GlobalInfo *g) static void clean_fifo(struct GlobalInfo *g) { - event_del(&g->fifo_event); - fclose(g->input); - unlink(fifo); + event_del(&g->fifo_event); + fclose(g->input); + unlink(fifo); } -int main(int argc, char **argv) +int main(void) { - CURLcode res; + CURLcode result; struct GlobalInfo g; - (void)argc; - (void)argv; - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; memset(&g, 0, sizeof(g)); g.evbase = event_base_new(); diff --git a/docs/examples/hsts-preload.c b/docs/examples/hsts-preload.c index 303b17f52500..9ae1ff5b0fa7 100644 --- a/docs/examples/hsts-preload.c +++ b/docs/examples/hsts-preload.c @@ -25,8 +25,15 @@ * Preload domains to HSTS * */ +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* for strcpy() */ +#endif +#endif + #include #include + #include struct entry { @@ -46,13 +53,12 @@ struct state { /* "read" is from the point of the library, it wants data from us. One domain entry per invoke. */ -static CURLSTScode hstsread(CURL *easy, struct curl_hstsentry *e, - void *userp) +static CURLSTScode hstsread(CURL *curl, struct curl_hstsentry *e, void *userp) { const char *host; const char *expire; struct state *s = (struct state *)userp; - (void)easy; + (void)curl; host = preload_hosts[s->index].name; expire = preload_hosts[s->index++].exp; @@ -67,10 +73,10 @@ static CURLSTScode hstsread(CURL *easy, struct curl_hstsentry *e, return CURLSTS_OK; } -static CURLSTScode hstswrite(CURL *easy, struct curl_hstsentry *e, +static CURLSTScode hstswrite(CURL *curl, struct curl_hstsentry *e, struct curl_index *i, void *userp) { - (void)easy; + (void)curl; (void)userp; /* we have no custom input */ printf("[%u/%u] %s %s\n", (unsigned int)i->index, (unsigned int)i->total, e->name, e->expire); @@ -81,13 +87,13 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { - struct state st = {0}; + struct state st = { 0 }; /* enable HSTS for this handle */ curl_easy_setopt(curl, CURLOPT_HSTS_CTRL, CURLHSTS_ENABLE); @@ -107,16 +113,16 @@ int main(void) curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/htmltidy.c b/docs/examples/htmltidy.c index 0bf3155570ce..3cd4f2a5ba7a 100644 --- a/docs/examples/htmltidy.c +++ b/docs/examples/htmltidy.c @@ -28,14 +28,15 @@ /* * LibTidy => https://www.html-tidy.org/ */ - #include + #include #include + #include /* curl write callback, to fill tidy's input buffer... */ -uint write_cb(char *in, uint size, uint nmemb, TidyBuffer *out) +static uint write_cb(char *in, uint size, uint nmemb, TidyBuffer *out) { uint r; r = size * nmemb; @@ -44,17 +45,17 @@ uint write_cb(char *in, uint size, uint nmemb, TidyBuffer *out) } /* Traverse the document tree */ -void dumpNode(TidyDoc doc, TidyNode tnod, int indent) +static void dumpNode(TidyDoc doc, TidyNode tnod, int indent) { TidyNode child; - for(child = tidyGetChild(tnod); child; child = tidyGetNext(child) ) { + for(child = tidyGetChild(tnod); child; child = tidyGetNext(child)) { ctmbstr name = tidyNodeGetName(child); if(name) { - /* if it has a name, then it's an HTML tag ... */ + /* if it has a name, then it is an HTML tag ... */ TidyAttr attr; printf("%*.*s%s ", indent, indent, "<", name); /* walk the attribute list */ - for(attr = tidyAttrFirst(child); attr; attr = tidyAttrNext(attr) ) { + for(attr = tidyAttrFirst(child); attr; attr = tidyAttrNext(attr)) { printf("%s", tidyAttrName(attr)); tidyAttrValue(attr) ? printf("=\"%s\" ", tidyAttrValue(attr)) : printf(" "); @@ -62,7 +63,7 @@ void dumpNode(TidyDoc doc, TidyNode tnod, int indent) printf(">\n"); } else { - /* if it does not have a name, then it's probably text, cdata, etc... */ + /* if it does not have a name, then it is probably text, cdata, etc... */ TidyBuffer buf; tidyBufInit(&buf); tidyNodeGetText(doc, child, &buf); @@ -73,24 +74,23 @@ void dumpNode(TidyDoc doc, TidyNode tnod, int indent) } } - int main(int argc, char **argv) { CURL *curl; char curl_errbuf[CURL_ERROR_SIZE]; TidyDoc tdoc; - TidyBuffer docbuf = {0}; - TidyBuffer tidy_errbuf = {0}; - CURLcode res; + TidyBuffer docbuf = { 0 }; + TidyBuffer tidy_errbuf = { 0 }; + CURLcode result; if(argc != 2) { printf("usage: %s \n", argv[0]); return 1; } - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; tdoc = tidyCreate(); tidyOptSetBool(tdoc, TidyForceOutput, yes); /* try harder */ @@ -107,14 +107,14 @@ int main(int argc, char **argv) curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &docbuf); - res = curl_easy_perform(curl); - if(!res) { - res = tidyParseBuffer(tdoc, &docbuf); /* parse the input */ - if(res >= 0) { - res = tidyCleanAndRepair(tdoc); /* fix any problems */ - if(res >= 0) { - res = tidyRunDiagnostics(tdoc); /* load tidy error buffer */ - if(res >= 0) { + result = curl_easy_perform(curl); + if(!result) { + result = tidyParseBuffer(tdoc, &docbuf); /* parse the input */ + if(result >= 0) { + result = tidyCleanAndRepair(tdoc); /* fix any problems */ + if(result >= 0) { + result = tidyRunDiagnostics(tdoc); /* load tidy error buffer */ + if(result >= 0) { dumpNode(tdoc, tidyGetRoot(tdoc), 0); /* walk the tree */ fprintf(stderr, "%s\n", tidy_errbuf.bp); /* show errors */ } @@ -134,5 +134,5 @@ int main(int argc, char **argv) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/htmltitle.cpp b/docs/examples/htmltitle.cpp index e4979ee859d3..84e02f5c6bfb 100644 --- a/docs/examples/htmltitle.cpp +++ b/docs/examples/htmltitle.cpp @@ -22,7 +22,7 @@ * ***************************************************************************/ /* - * Get a web page, extract the title with libxml. + * Get a webpage, extract the title with libxml. * Written by Lars Nilsson @@ -36,7 +36,9 @@ #include #include #include + #include + #include // @@ -44,18 +46,16 @@ // #ifdef _WIN32 -#define COMPARE(a, b) (!_stricmp((a), (b))) +#define COMPARE(a, b) (!_stricmp(a, b)) #else -#define COMPARE(a, b) (!strcasecmp((a), (b))) +#define COMPARE(a, b) (!strcasecmp(a, b)) #endif // // libxml callback context structure // - -struct Context -{ - Context(): addTitle(false) { } +struct Context { + Context() : addTitle(false) {} bool addTitle; std::string title; @@ -70,14 +70,13 @@ static std::string buffer; // // libcurl write callback function // - static size_t writer(char *data, size_t size, size_t nmemb, std::string *writerData) { if(writerData == NULL) return 0; - writerData->append(data, size*nmemb); + writerData->append(data, size * nmemb); return size * nmemb; } @@ -85,44 +84,43 @@ static size_t writer(char *data, size_t size, size_t nmemb, // // libcurl connection initialization // - -static bool init(CURL *&conn, const char *url) +static bool init(CURL *&curl, const char *url) { - CURLcode code; + CURLcode result; - conn = curl_easy_init(); + curl = curl_easy_init(); - if(conn == NULL) { - fprintf(stderr, "Failed to create CURL connection\n"); + if(!curl) { + fprintf(stderr, "Failed to create CURL handle\n"); return false; } - code = curl_easy_setopt(conn, CURLOPT_ERRORBUFFER, errorBuffer); - if(code != CURLE_OK) { - fprintf(stderr, "Failed to set error buffer [%d]\n", code); + result = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer); + if(result != CURLE_OK) { + fprintf(stderr, "Failed to set error buffer [%d]\n", result); return false; } - code = curl_easy_setopt(conn, CURLOPT_URL, url); - if(code != CURLE_OK) { + result = curl_easy_setopt(curl, CURLOPT_URL, url); + if(result != CURLE_OK) { fprintf(stderr, "Failed to set URL [%s]\n", errorBuffer); return false; } - code = curl_easy_setopt(conn, CURLOPT_FOLLOWLOCATION, 1L); - if(code != CURLE_OK) { + result = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); + if(result != CURLE_OK) { fprintf(stderr, "Failed to set redirect option [%s]\n", errorBuffer); return false; } - code = curl_easy_setopt(conn, CURLOPT_WRITEFUNCTION, writer); - if(code != CURLE_OK) { + result = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer); + if(result != CURLE_OK) { fprintf(stderr, "Failed to set writer [%s]\n", errorBuffer); return false; } - code = curl_easy_setopt(conn, CURLOPT_WRITEDATA, &buffer); - if(code != CURLE_OK) { + result = curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer); + if(result != CURLE_OK) { fprintf(stderr, "Failed to set write data [%s]\n", errorBuffer); return false; } @@ -133,7 +131,6 @@ static bool init(CURL *&conn, const char *url) // // libxml start element callback function // - static void StartElement(void *voidContext, const xmlChar *name, const xmlChar **attributes) @@ -150,7 +147,6 @@ static void StartElement(void *voidContext, // // libxml end element callback function // - static void EndElement(void *voidContext, const xmlChar *name) { @@ -163,7 +159,6 @@ static void EndElement(void *voidContext, // // Text handling helper function // - static void handleCharacters(Context *context, const xmlChar *chars, int length) @@ -176,7 +171,6 @@ static void handleCharacters(Context *context, // // libxml PCDATA callback function // - static void Characters(void *voidContext, const xmlChar *chars, int length) @@ -189,7 +183,6 @@ static void Characters(void *voidContext, // // libxml CDATA callback function // - static void cdata(void *voidContext, const xmlChar *chars, int length) @@ -202,9 +195,7 @@ static void cdata(void *voidContext, // // libxml SAX callback structure // - -static htmlSAXHandler saxHandler = -{ +static htmlSAXHandler saxHandler = { NULL, NULL, NULL, @@ -242,7 +233,6 @@ static htmlSAXHandler saxHandler = // // Parse given (assumed to be) HTML text and return the title // - static void parseHtml(const std::string &html, std::string &title) { @@ -262,8 +252,8 @@ static void parseHtml(const std::string &html, int main(int argc, char *argv[]) { - CURL *conn = NULL; - CURLcode res; + CURL *curl = NULL; + CURLcode result; std::string title; // Ensure one argument is given @@ -273,24 +263,24 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; - // Initialize CURL connection + // Initialize CURL handle - if(!init(conn, argv[1])) { - fprintf(stderr, "Connection initialization failed\n"); + if(!init(curl, argv[1])) { + fprintf(stderr, "Handle initialization failed\n"); curl_global_cleanup(); return EXIT_FAILURE; } // Retrieve content for the URL - res = curl_easy_perform(conn); - curl_easy_cleanup(conn); + result = curl_easy_perform(curl); + curl_easy_cleanup(curl); - if(res != CURLE_OK) { + if(result != CURLE_OK) { fprintf(stderr, "Failed to get '%s' [%s]\n", argv[1], errorBuffer); return EXIT_FAILURE; } @@ -301,5 +291,5 @@ int main(int argc, char *argv[]) // Display the extracted title printf("Title: %s\n", title.c_str()); - return (int)res; + return (int)result; } diff --git a/docs/examples/http-options.c b/docs/examples/http-options.c index 9520670baeab..105f99643683 100644 --- a/docs/examples/http-options.c +++ b/docs/examples/http-options.c @@ -26,15 +26,16 @@ * */ #include + #include int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -48,12 +49,12 @@ int main(void) from libcurl as this exits anyway */ curl_easy_setopt(curl, CURLOPT_QUICK_EXIT, 1L); - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); diff --git a/docs/examples/http-post.c b/docs/examples/http-post.c index fb91822bb8ab..dac8953b727c 100644 --- a/docs/examples/http-post.c +++ b/docs/examples/http-post.c @@ -26,17 +26,18 @@ * */ #include + #include int main(void) { CURL *curl; - CURLcode res; + CURLcode result; /* In Windows, this inits the Winsock stuff */ - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; /* get a curl handle */ curl = curl_easy_init(); @@ -48,16 +49,16 @@ int main(void) /* Now specify the POST data */ curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "name=daniel&project=curl"); - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/http2-download.c b/docs/examples/http2-download.c index 06902415e18d..a9a0a8a9f7b2 100644 --- a/docs/examples/http2-download.c +++ b/docs/examples/http2-download.c @@ -25,22 +25,19 @@ * Multiplexed HTTP/2 downloads over a single connection * */ +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* for _snprintf(), fopen(), strerror() */ +#endif +#endif + #include #include #include -#ifdef UNDER_CE -#define strerror(e) "?" -#else #include -#endif -/* curl stuff */ #include -#if defined(_MSC_VER) && (_MSC_VER < 1900) -#define snprintf _snprintf -#endif - #ifndef CURLPIPE_MULTIPLEX /* This little trick makes sure that we do not enable pipelining for libcurls old enough to not have this symbol. It is _not_ defined to zero in a recent @@ -48,27 +45,28 @@ #define CURLPIPE_MULTIPLEX 0L #endif +#if defined(_MSC_VER) && (_MSC_VER < 1900) +#define snprintf _snprintf +#endif + struct transfer { - CURL *easy; - unsigned int num; FILE *out; + CURL *curl; + int num; }; -#define NUM_HANDLES 1000 - -static void dump(const char *text, unsigned int num, unsigned char *ptr, +static void dump(const char *text, int num, unsigned char *ptr, size_t size, char nohex) { size_t i; size_t c; - unsigned int width = 0x10; if(nohex) /* without the hex output, we can fit more on screen */ width = 0x40; - fprintf(stderr, "%u %s, %lu bytes (0x%lx)\n", + fprintf(stderr, "%d %s, %lu bytes (0x%lx)\n", num, text, (unsigned long)size, (unsigned long)size); for(i = 0; i < size; i += width) { @@ -93,7 +91,7 @@ static void dump(const char *text, unsigned int num, unsigned char *ptr, } fprintf(stderr, "%c", (ptr[i + c] >= 0x20) && (ptr[i + c] < 0x80) ? ptr[i + c] : '.'); - /* check again for 0D0A, to avoid an extra \n if it's at width */ + /* check again for 0D0A, to avoid an extra \n if it is at width */ if(nohex && (i + c + 2 < size) && ptr[i + c + 1] == 0x0D && ptr[i + c + 2] == 0x0A) { i += (c + 3 - width); @@ -104,17 +102,17 @@ static void dump(const char *text, unsigned int num, unsigned char *ptr, } } -static int my_trace(CURL *handle, curl_infotype type, +static int my_trace(CURL *curl, curl_infotype type, char *data, size_t size, void *userp) { const char *text; struct transfer *t = (struct transfer *)userp; - unsigned int num = t->num; - (void)handle; + int num = t->num; + (void)curl; switch(type) { case CURLINFO_TEXT: - fprintf(stderr, "== %u Info: %s", num, data); + fprintf(stderr, "== [%d] Info: %s", num, data); return 0; case CURLINFO_HEADER_OUT: text = "=> Send header"; @@ -145,12 +143,12 @@ static int my_trace(CURL *handle, curl_infotype type, static int setup(struct transfer *t, int num) { char filename[128]; - CURL *hnd; + CURL *curl; - hnd = t->easy = curl_easy_init(); + curl = t->curl = NULL; + t->num = num; snprintf(filename, sizeof(filename), "dl-%d", num); - t->out = fopen(filename, "wb"); if(!t->out) { fprintf(stderr, "error: could not open file %s for writing: %s\n", @@ -158,27 +156,31 @@ static int setup(struct transfer *t, int num) return 1; } - /* write to this file */ - curl_easy_setopt(hnd, CURLOPT_WRITEDATA, t->out); + curl = t->curl = curl_easy_init(); + if(curl) { - /* set the same URL */ - curl_easy_setopt(hnd, CURLOPT_URL, "https://localhost:8443/index.html"); + /* write to this file */ + curl_easy_setopt(curl, CURLOPT_WRITEDATA, t->out); - /* please be verbose */ - curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); - curl_easy_setopt(hnd, CURLOPT_DEBUGFUNCTION, my_trace); - curl_easy_setopt(hnd, CURLOPT_DEBUGDATA, t); + /* set the same URL */ + curl_easy_setopt(curl, CURLOPT_URL, "https://localhost:8443/index.html"); - /* enlarge the receive buffer for potentially higher transfer speeds */ - curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 100000L); + /* please be verbose */ + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); + curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace); + curl_easy_setopt(curl, CURLOPT_DEBUGDATA, t); - /* HTTP/2 please */ - curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); + /* enlarge the receive buffer for potentially higher transfer speeds */ + curl_easy_setopt(curl, CURLOPT_BUFFERSIZE, 100000L); + + /* HTTP/2 please */ + curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); #if (CURLPIPE_MULTIPLEX > 0) - /* wait for pipe connection to confirm */ - curl_easy_setopt(hnd, CURLOPT_PIPEWAIT, 1L); + /* wait for pipe connection to confirm */ + curl_easy_setopt(curl, CURLOPT_PIPEWAIT, 1L); #endif + } return 0; } @@ -187,9 +189,9 @@ static int setup(struct transfer *t, int num) */ int main(int argc, char **argv) { - CURLcode res; - struct transfer trans[NUM_HANDLES]; - CURLM *multi_handle; + CURLcode result; + struct transfer *trans; + CURLM *multi = NULL; int i; int still_running = 0; /* keep number of running handles */ int num_transfers; @@ -197,50 +199,65 @@ int main(int argc, char **argv) if(argc > 1) { /* if given a number, do that many transfers */ num_transfers = atoi(argv[1]); - if((num_transfers < 1) || (num_transfers > NUM_HANDLES)) + if((num_transfers < 1) || (num_transfers > 1000)) num_transfers = 3; /* a suitable low default */ } else - num_transfers = 3; /* suitable default */ + num_transfers = 3; /* a suitable low default */ - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; - memset(trans, 0, sizeof(trans)); + trans = calloc(num_transfers, sizeof(*trans)); + if(!trans) { + fprintf(stderr, "error allocating transfer structs\n"); + goto error; + } /* init a multi stack */ - multi_handle = curl_multi_init(); + multi = curl_multi_init(); + if(!multi) + goto error; for(i = 0; i < num_transfers; i++) { if(setup(&trans[i], i)) { - curl_global_cleanup(); - return 1; + goto error; } /* add the individual transfer */ - curl_multi_add_handle(multi_handle, trans[i].easy); + curl_multi_add_handle(multi, trans[i].curl); } - curl_multi_setopt(multi_handle, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX); + curl_multi_setopt(multi, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX); do { - CURLMcode mc = curl_multi_perform(multi_handle, &still_running); + CURLMcode mresult = curl_multi_perform(multi, &still_running); if(still_running) /* wait for activity, timeout or "nothing" */ - mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL); + mresult = curl_multi_poll(multi, NULL, 0, 1000, NULL); - if(mc) + if(mresult) break; + } while(still_running); - for(i = 0; i < num_transfers; i++) { - curl_multi_remove_handle(multi_handle, trans[i].easy); - curl_easy_cleanup(trans[i].easy); +error: + + if(multi) { + for(i = 0; i < num_transfers; i++) { + curl_multi_remove_handle(multi, trans[i].curl); + curl_easy_cleanup(trans[i].curl); + + if(trans[i].out) + fclose(trans[i].out); + } + curl_multi_cleanup(multi); } - curl_multi_cleanup(multi_handle); + free(trans); + curl_global_cleanup(); return 0; diff --git a/docs/examples/http2-pushinmemory.c b/docs/examples/http2-pushinmemory.c index 85bf0e34a745..37816742c0b3 100644 --- a/docs/examples/http2-pushinmemory.c +++ b/docs/examples/http2-pushinmemory.c @@ -29,7 +29,6 @@ #include #include -/* curl stuff */ #include struct Memory { @@ -66,30 +65,30 @@ static void init_memory(struct Memory *chunk) chunk->size = 0; /* no data at this point */ } -static void setup(CURL *hnd) +static void setup(CURL *curl) { /* set the same URL */ - curl_easy_setopt(hnd, CURLOPT_URL, "https://localhost:8443/index.html"); + curl_easy_setopt(curl, CURLOPT_URL, "https://localhost:8443/index.html"); /* HTTP/2 please */ - curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); + curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); /* we use a self-signed test server, skip verification during debugging */ - curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYPEER, 0L); - curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); /* write data to a struct */ - curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, write_cb); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); init_memory(&files[0]); - curl_easy_setopt(hnd, CURLOPT_WRITEDATA, &files[0]); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &files[0]); /* wait for pipe connection to confirm */ - curl_easy_setopt(hnd, CURLOPT_PIPEWAIT, 1L); + curl_easy_setopt(curl, CURLOPT_PIPEWAIT, 1L); } /* called when there is an incoming push */ static int server_push_callback(CURL *parent, - CURL *easy, + CURL *curl, size_t num_headers, struct curl_pushheaders *headers, void *userp) @@ -105,7 +104,7 @@ static int server_push_callback(CURL *parent, /* write to this buffer */ init_memory(&files[pushindex]); - curl_easy_setopt(easy, CURLOPT_WRITEDATA, &files[pushindex]); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &files[pushindex]); pushindex++; headp = curl_pushheader_byname(headers, ":path"); @@ -116,31 +115,30 @@ static int server_push_callback(CURL *parent, return CURL_PUSH_OK; } - /* * Download a file over HTTP/2, take care of server push. */ int main(void) { - CURL *easy; + CURL *curl; CURLM *multi; int transfers = 1; /* we start with one */ int i; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; /* init a multi stack */ multi = curl_multi_init(); - easy = curl_easy_init(); + curl = curl_easy_init(); /* set options */ - setup(easy); + setup(curl); /* add the easy transfer */ - curl_multi_add_handle(multi, easy); + curl_multi_add_handle(multi, curl); curl_multi_setopt(multi, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX); curl_multi_setopt(multi, CURLMOPT_PUSHFUNCTION, server_push_callback); @@ -151,12 +149,12 @@ int main(void) int still_running; /* keep number of running handles */ int rc; - CURLMcode mcode = curl_multi_perform(multi, &still_running); - if(mcode) + CURLMcode mresult = curl_multi_perform(multi, &still_running); + if(mresult) break; - mcode = curl_multi_wait(multi, NULL, 0, 1000, &rc); - if(mcode) + mresult = curl_multi_wait(multi, NULL, 0, 1000, &rc); + if(mresult) break; /* @@ -167,10 +165,10 @@ int main(void) int msgq = 0; m = curl_multi_info_read(multi, &msgq); if(m && (m->msg == CURLMSG_DONE)) { - CURL *e = m->easy_handle; + curl = m->easy_handle; transfers--; - curl_multi_remove_handle(multi, e); - curl_easy_cleanup(e); + curl_multi_remove_handle(multi, curl); + curl_easy_cleanup(curl); } } while(m); } diff --git a/docs/examples/http2-serverpush.c b/docs/examples/http2-serverpush.c index e97be991a8cb..e646ce1e4b6c 100644 --- a/docs/examples/http2-serverpush.c +++ b/docs/examples/http2-serverpush.c @@ -25,20 +25,27 @@ * HTTP/2 server push * */ +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* for _snprintf(), fopen() */ +#endif +#endif + #include #include #include -/* curl stuff */ #include +#ifndef CURLPIPE_MULTIPLEX +#error "too old libcurl, cannot do HTTP/2 server push!" +#endif + #if defined(_MSC_VER) && (_MSC_VER < 1900) #define snprintf _snprintf #endif -#ifndef CURLPIPE_MULTIPLEX -#error "too old libcurl, cannot do HTTP/2 server push!" -#endif +static FILE *out_download; static void dump(const char *text, unsigned char *ptr, size_t size, char nohex) { @@ -76,7 +83,7 @@ static void dump(const char *text, unsigned char *ptr, size_t size, char nohex) } fprintf(stderr, "%c", (ptr[i + c] >= 0x20) && (ptr[i + c] < 0x80) ? ptr[i + c] : '.'); - /* check again for 0D0A, to avoid an extra \n if it's at width */ + /* check again for 0D0A, to avoid an extra \n if it is at width */ if(nohex && (i + c + 2 < size) && ptr[i + c + 1] == 0x0D && ptr[i + c + 2] == 0x0A) { i += (c + 3 - width); @@ -87,11 +94,11 @@ static void dump(const char *text, unsigned char *ptr, size_t size, char nohex) } } -static int my_trace(CURL *handle, curl_infotype type, +static int my_trace(CURL *curl, curl_infotype type, char *data, size_t size, void *userp) { const char *text; - (void)handle; + (void)curl; (void)userp; switch(type) { case CURLINFO_TEXT: @@ -125,40 +132,41 @@ static int my_trace(CURL *handle, curl_infotype type, #define OUTPUTFILE "dl" -static int setup(CURL *hnd, const char *url) +static int setup(CURL *curl, const char *url) { - FILE *out = fopen(OUTPUTFILE, "wb"); - if(!out) - /* failed */ - return 1; - - /* write to this file */ - curl_easy_setopt(hnd, CURLOPT_WRITEDATA, out); + out_download = fopen(OUTPUTFILE, "wb"); + if(!out_download) + return 1; /* failed */ /* set the same URL */ - curl_easy_setopt(hnd, CURLOPT_URL, url); - - /* please be verbose */ - curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); - curl_easy_setopt(hnd, CURLOPT_DEBUGFUNCTION, my_trace); + curl_easy_setopt(curl, CURLOPT_URL, url); /* HTTP/2 please */ - curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); + curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); /* we use a self-signed test server, skip verification during debugging */ - curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYPEER, 0L); - curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); -#if (CURLPIPE_MULTIPLEX > 0) + /* write to this file */ + curl_easy_setopt(curl, CURLOPT_WRITEDATA, out_download); + + /* please be verbose */ + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); + curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace); + +#if CURLPIPE_MULTIPLEX > 0 /* wait for pipe connection to confirm */ - curl_easy_setopt(hnd, CURLOPT_PIPEWAIT, 1L); + curl_easy_setopt(curl, CURLOPT_PIPEWAIT, 1L); #endif return 0; /* all is good */ } +static FILE *out_push; + /* called when there is an incoming push */ static int server_push_callback(CURL *parent, - CURL *easy, + CURL *curl, size_t num_headers, struct curl_pushheaders *headers, void *userp) @@ -167,7 +175,6 @@ static int server_push_callback(CURL *parent, size_t i; int *transfers = (int *)userp; char filename[128]; - FILE *out; static unsigned int count = 0; (void)parent; @@ -175,15 +182,15 @@ static int server_push_callback(CURL *parent, snprintf(filename, sizeof(filename), "push%u", count++); /* here's a new stream, save it in a new file for each new push */ - out = fopen(filename, "wb"); - if(!out) { + out_push = fopen(filename, "wb"); + if(!out_push) { /* if we cannot save it, deny it */ fprintf(stderr, "Failed to create output file for push\n"); return CURL_PUSH_DENY; } /* write to this file */ - curl_easy_setopt(easy, CURLOPT_WRITEDATA, out); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, out_push); fprintf(stderr, "**** push callback approves stream %u, got %lu headers!\n", count, (unsigned long)num_headers); @@ -199,57 +206,58 @@ static int server_push_callback(CURL *parent, } (*transfers)++; /* one more */ + return CURL_PUSH_OK; } - /* * Download a file over HTTP/2, take care of server push. */ int main(int argc, char *argv[]) { - CURLcode res; - CURL *easy; - CURLM *multi_handle; + CURLcode result; + CURL *curl; + CURLM *multi; int transfers = 1; /* we start with one */ const char *url = "https://localhost:8443/index.html"; if(argc == 2) url = argv[1]; - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; /* init a multi stack */ - multi_handle = curl_multi_init(); + multi = curl_multi_init(); + if(!multi) + goto error; - easy = curl_easy_init(); + curl = curl_easy_init(); /* set options */ - if(setup(easy, url)) { + if(!curl || setup(curl, url)) { fprintf(stderr, "failed\n"); - curl_global_cleanup(); - return 1; + goto error; } - /* add the easy transfer */ - curl_multi_add_handle(multi_handle, easy); + curl_multi_setopt(multi, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX); + curl_multi_setopt(multi, CURLMOPT_PUSHFUNCTION, server_push_callback); + curl_multi_setopt(multi, CURLMOPT_PUSHDATA, &transfers); - curl_multi_setopt(multi_handle, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX); - curl_multi_setopt(multi_handle, CURLMOPT_PUSHFUNCTION, server_push_callback); - curl_multi_setopt(multi_handle, CURLMOPT_PUSHDATA, &transfers); + /* add the easy transfer */ + curl_multi_add_handle(multi, curl); do { struct CURLMsg *m; int still_running; /* keep number of running handles */ - CURLMcode mc = curl_multi_perform(multi_handle, &still_running); + CURLMcode mresult = curl_multi_perform(multi, &still_running); if(still_running) /* wait for activity, timeout or "nothing" */ - mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL); + mresult = curl_multi_poll(multi, NULL, 0, 1000, NULL); - if(mc) + if(mresult) break; /* @@ -257,22 +265,29 @@ int main(int argc, char *argv[]) * created and added one or more easy handles but we need to clean them up * when we are done. */ - do { int msgq = 0; - m = curl_multi_info_read(multi_handle, &msgq); + m = curl_multi_info_read(multi, &msgq); if(m && (m->msg == CURLMSG_DONE)) { - CURL *e = m->easy_handle; + curl = m->easy_handle; transfers--; - curl_multi_remove_handle(multi_handle, e); - curl_easy_cleanup(e); + curl_multi_remove_handle(multi, curl); + curl_easy_cleanup(curl); } } while(m); } while(transfers); /* as long as we have transfers going */ - curl_multi_cleanup(multi_handle); +error: + + if(multi) + curl_multi_cleanup(multi); + curl_global_cleanup(); + fclose(out_download); + if(out_push) + fclose(out_push); + return 0; } diff --git a/docs/examples/http2-upload.c b/docs/examples/http2-upload.c index 55162c03a3ad..1ebc993bfd6f 100644 --- a/docs/examples/http2-upload.c +++ b/docs/examples/http2-upload.c @@ -25,16 +25,19 @@ * Multiplexed HTTP/2 uploads over a single connection * */ +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* for _snprintf(), fopen(), localtime(), + strerror() */ +#endif +#endif + #include #include #include #include #include -#ifdef UNDER_CE -#define strerror(e) "?" -#else #include -#endif /* somewhat Unix-specific */ #ifndef _MSC_VER @@ -42,19 +45,6 @@ #include #endif -#ifdef _WIN32 -#undef stat -#define stat _stat -#undef fstat -#define fstat _fstat -#define fileno _fileno -#endif - -#if defined(_MSC_VER) && (_MSC_VER < 1900) -#define snprintf _snprintf -#endif - -/* curl stuff */ #include #ifndef CURLPIPE_MULTIPLEX @@ -64,16 +54,26 @@ #define CURLPIPE_MULTIPLEX 0L #endif -#define NUM_HANDLES 1000 +#ifdef _WIN32 +#undef stat +#define stat _stati64 +#undef fstat +#define fstat _fstati64 +#define fileno _fileno +#endif + +#if defined(_MSC_VER) && (_MSC_VER < 1900) +#define snprintf _snprintf +#endif #ifdef _MSC_VER -#define gettimeofday(a, b) my_gettimeofday((a), (b)) +#define gettimeofday(a, b) my_gettimeofday(a, b) static int my_gettimeofday(struct timeval *tp, void *tzp) { (void)tzp; if(tp) { - /* Offset between 1601-01-01 and 1970-01-01 in 100 nanosec units */ - #define WIN32_FT_OFFSET (116444736000000000) +/* Offset between 1601-01-01 and 1970-01-01 in 100 nanosec units */ +#define WIN32_FT_OFFSET (116444736000000000) union { CURL_TYPEOF_CURL_OFF_T ns100; /* time since 1 Jan 1601 in 100ns units */ FILETIME ft; @@ -90,12 +90,12 @@ struct input { FILE *in; FILE *out; size_t bytes_read; /* count up */ - CURL *hnd; + CURL *curl; int num; }; -static void dump(const char *text, int num, unsigned char *ptr, size_t size, - char nohex) +static void dump(const char *text, int num, const unsigned char *ptr, + size_t size, char nohex) { size_t i; size_t c; @@ -130,7 +130,7 @@ static void dump(const char *text, int num, unsigned char *ptr, size_t size, } fprintf(stderr, "%c", (ptr[i + c] >= 0x20) && (ptr[i + c] < 0x80) ? ptr[i + c] : '.'); - /* check again for 0D0A, to avoid an extra \n if it's at width */ + /* check again for 0D0A, to avoid an extra \n if it is at width */ if(nohex && (i + c + 2 < size) && ptr[i + c + 1] == 0x0D && ptr[i + c + 2] == 0x0A) { i += (c + 3 - width); @@ -141,8 +141,8 @@ static void dump(const char *text, int num, unsigned char *ptr, size_t size, } } -static int my_trace(CURL *handle, curl_infotype type, char *data, - size_t size, void *userp) +static int my_trace(CURL *curl, curl_infotype type, + char *data, size_t size, void *userp) { char timebuf[60]; const char *text; @@ -153,7 +153,7 @@ static int my_trace(CURL *handle, curl_infotype type, char *data, struct timeval tv; time_t secs; struct tm *now; - (void)handle; + (void)curl; gettimeofday(&tv, NULL); if(!known_offset) { @@ -161,7 +161,7 @@ static int my_trace(CURL *handle, curl_infotype type, char *data, known_offset = 1; } secs = epoch_offset + tv.tv_sec; - now = localtime(&secs); /* not thread safe but we do not care */ + now = localtime(&secs); /* not thread-safe but we do not care */ snprintf(timebuf, sizeof(timebuf), "%02d:%02d:%02d.%06ld", now->tm_hour, now->tm_min, now->tm_sec, (long)tv.tv_usec); @@ -195,7 +195,7 @@ static int my_trace(CURL *handle, curl_infotype type, char *data, return 0; } -static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp) +static size_t read_cb(char *ptr, size_t size, size_t nmemb, void *userp) { struct input *i = userp; size_t retcode = fread(ptr, size, nmemb, i->in); @@ -203,85 +203,80 @@ static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *userp) return retcode; } -static int setup(struct input *i, int num, const char *upload) +static int setup(struct input *t, int num, const char *upload) { char url[256]; char filename[128]; struct stat file_info; curl_off_t uploadsize; - CURL *hnd; + CURL *curl; - hnd = i->hnd = NULL; + curl = t->curl = NULL; - i->num = num; + t->num = num; snprintf(filename, sizeof(filename), "dl-%d", num); - i->out = fopen(filename, "wb"); - if(!i->out) { - fprintf(stderr, "error: could not open file %s for writing: %s\n", upload, - strerror(errno)); + t->out = fopen(filename, "wb"); + if(!t->out) { + fprintf(stderr, "error: could not open file %s for writing: %s\n", + upload, strerror(errno)); return 1; } snprintf(url, sizeof(url), "https://localhost:8443/upload-%d", num); - i->in = fopen(upload, "rb"); - if(!i->in) { - fprintf(stderr, "error: could not open file %s for reading: %s\n", upload, - strerror(errno)); - fclose(i->out); - i->out = NULL; + t->in = fopen(upload, "rb"); + if(!t->in) { + fprintf(stderr, "error: could not open file %s for reading: %s\n", + upload, strerror(errno)); + fclose(t->out); + t->out = NULL; return 1; } -#ifdef UNDER_CE - /* !checksrc! disable BANNEDFUNC 1 */ - if(stat(upload, &file_info) != 0) { -#else - if(fstat(fileno(i->in), &file_info) != 0) { -#endif + if(fstat(fileno(t->in), &file_info) != 0) { fprintf(stderr, "error: could not stat file %s: %s\n", upload, strerror(errno)); - fclose(i->out); - i->out = NULL; + fclose(t->out); + t->out = NULL; return 1; } uploadsize = file_info.st_size; - hnd = i->hnd = curl_easy_init(); - if(hnd) { + curl = t->curl = curl_easy_init(); + if(curl) { /* write to this file */ - curl_easy_setopt(hnd, CURLOPT_WRITEDATA, i->out); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, t->out); /* we want to use our own read function */ - curl_easy_setopt(hnd, CURLOPT_READFUNCTION, read_callback); + curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_cb); /* read from this file */ - curl_easy_setopt(hnd, CURLOPT_READDATA, i); + curl_easy_setopt(curl, CURLOPT_READDATA, t); /* provide the size of the upload */ - curl_easy_setopt(hnd, CURLOPT_INFILESIZE_LARGE, uploadsize); + curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, uploadsize); /* send in the URL to store the upload as */ - curl_easy_setopt(hnd, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_URL, url); /* upload please */ - curl_easy_setopt(hnd, CURLOPT_UPLOAD, 1L); + curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); /* please be verbose */ - curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); - curl_easy_setopt(hnd, CURLOPT_DEBUGFUNCTION, my_trace); - curl_easy_setopt(hnd, CURLOPT_DEBUGDATA, i); + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); + curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace); + curl_easy_setopt(curl, CURLOPT_DEBUGDATA, t); /* HTTP/2 please */ - curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); + curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); /* we use a self-signed test server, skip verification during debugging */ - curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYPEER, 0L); - curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYHOST, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); #if (CURLPIPE_MULTIPLEX > 0) /* wait for pipe connection to confirm */ - curl_easy_setopt(hnd, CURLOPT_PIPEWAIT, 1L); + curl_easy_setopt(curl, CURLOPT_PIPEWAIT, 1L); #endif } return 0; @@ -292,81 +287,85 @@ static int setup(struct input *i, int num, const char *upload) */ int main(int argc, char **argv) { - CURLcode res; - struct input trans[NUM_HANDLES]; - CURLM *multi_handle; + CURLcode result; + struct input *trans; + CURLM *multi = NULL; int i; const char *filename = "index.html"; + int still_running = 0; /* keep number of running handles */ int num_transfers; if(argc > 1) { /* if given a number, do that many transfers */ num_transfers = atoi(argv[1]); - - if(!num_transfers || (num_transfers > NUM_HANDLES)) - num_transfers = 3; /* a suitable low default */ + if((num_transfers < 1) || (num_transfers > 1000)) + num_transfers = 3; /* a suitable low default */ if(argc > 2) - /* if given a file name, upload this! */ + /* if given a filename, upload this! */ filename = argv[2]; } else - num_transfers = 3; + num_transfers = 3; /* a suitable low default */ - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; - memset(trans, 0, sizeof(trans)); + trans = calloc(num_transfers, sizeof(*trans)); + if(!trans) { + fprintf(stderr, "error allocating transfer structs\n"); + goto error; + } /* init a multi stack */ - multi_handle = curl_multi_init(); - if(multi_handle) { - - int still_running = 0; /* keep number of running handles */ - - for(i = 0; i < num_transfers; i++) { - if(setup(&trans[i], i, filename)) { - curl_global_cleanup(); - return 1; - } + multi = curl_multi_init(); + if(!multi) + goto error; - /* add the individual transfer */ - curl_multi_add_handle(multi_handle, trans[i].hnd); + for(i = 0; i < num_transfers; i++) { + if(setup(&trans[i], i, filename)) { + goto error; } - curl_multi_setopt(multi_handle, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX); + /* add the individual transfer */ + curl_multi_add_handle(multi, trans[i].curl); + } - /* We do HTTP/2 so let's stick to one connection per host */ - curl_multi_setopt(multi_handle, CURLMOPT_MAX_HOST_CONNECTIONS, 1L); + curl_multi_setopt(multi, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX); - do { - CURLMcode mc = curl_multi_perform(multi_handle, &still_running); + /* We do HTTP/2 so let's stick to one connection per host */ + curl_multi_setopt(multi, CURLMOPT_MAX_HOST_CONNECTIONS, 1L); - if(still_running) - /* wait for activity, timeout or "nothing" */ - mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL); + do { + CURLMcode mresult = curl_multi_perform(multi, &still_running); - if(mc) - break; + if(still_running) + /* wait for activity, timeout or "nothing" */ + mresult = curl_multi_poll(multi, NULL, 0, 1000, NULL); - } while(still_running); + if(mresult) + break; - for(i = 0; i < num_transfers; i++) - curl_multi_remove_handle(multi_handle, trans[i].hnd); + } while(still_running); - curl_multi_cleanup(multi_handle); - } +error: - for(i = 0; i < num_transfers; i++) { - curl_easy_cleanup(trans[i].hnd); + if(multi) { + for(i = 0; i < num_transfers; i++) { + curl_multi_remove_handle(multi, trans[i].curl); + curl_easy_cleanup(trans[i].curl); - if(trans[i].in) - fclose(trans[i].in); - if(trans[i].out) - fclose(trans[i].out); + if(trans[i].in) + fclose(trans[i].in); + if(trans[i].out) + fclose(trans[i].out); + } + curl_multi_cleanup(multi); } + free(trans); + curl_global_cleanup(); return 0; diff --git a/docs/examples/http3-present.c b/docs/examples/http3-present.c index 084f265c46a9..ee9bdce2d919 100644 --- a/docs/examples/http3-present.c +++ b/docs/examples/http3-present.c @@ -26,15 +26,16 @@ * */ #include + #include int main(void) { curl_version_info_data *ver; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; ver = curl_version_info(CURLVERSION_NOW); if(ver->features & CURL_VERSION_HTTP2) diff --git a/docs/examples/http3.c b/docs/examples/http3.c index 323f6d7d17b6..702c7d9ac39e 100644 --- a/docs/examples/http3.c +++ b/docs/examples/http3.c @@ -22,19 +22,20 @@ * ***************************************************************************/ /* - * Very simple HTTP/3 GET + * Simple HTTP/3 GET * */ #include + #include int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -43,12 +44,12 @@ int main(void) /* Use HTTP/3 but fallback to earlier HTTP if necessary */ curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_3); - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); diff --git a/docs/examples/httpcustomheader.c b/docs/examples/httpcustomheader.c index 0657313ddf6c..7888dfab381a 100644 --- a/docs/examples/httpcustomheader.c +++ b/docs/examples/httpcustomheader.c @@ -26,15 +26,16 @@ * */ #include + #include int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -59,11 +60,11 @@ int main(void) curl_easy_setopt(curl, CURLOPT_URL, "localhost"); curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); @@ -72,5 +73,5 @@ int main(void) curl_slist_free_all(chunk); } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/httpput-postfields.c b/docs/examples/httpput-postfields.c index b855f454aec4..7163756a3658 100644 --- a/docs/examples/httpput-postfields.c +++ b/docs/examples/httpput-postfields.c @@ -27,9 +27,10 @@ */ #include #include + #include -static const char olivertwist[]= +static const char olivertwist[] = "Among other public buildings in a certain town, which for many reasons " "it will be prudent to refrain from mentioning, and to which I will assign " "no fictitious name, there is one anciently common to most towns, great or " @@ -49,7 +50,7 @@ static const char olivertwist[]= int main(int argc, char **argv) { CURL *curl; - CURLcode res; + CURLcode result; char *url; if(argc < 2) @@ -58,9 +59,9 @@ int main(int argc, char **argv) url = argv[1]; /* In Windows, this inits the Winsock stuff */ - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; /* get a curl handle */ curl = curl_easy_init(); @@ -88,11 +89,11 @@ int main(int argc, char **argv) curl_easy_setopt(curl, CURLOPT_URL, url); /* Now run off and do what you have been told! */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); @@ -102,5 +103,5 @@ int main(int argc, char **argv) } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/httpput.c b/docs/examples/httpput.c index 2aef62fc6713..9a8163ce88a4 100644 --- a/docs/examples/httpput.c +++ b/docs/examples/httpput.c @@ -25,16 +25,23 @@ * HTTP PUT with easy interface and read callback * */ +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* for fopen() */ +#endif +#endif + #include #include #include + #include #ifdef _WIN32 #undef stat -#define stat _stat +#define stat _stati64 #undef fstat -#define fstat _fstat +#define fstat _fstati64 #define fileno _fileno #endif @@ -48,7 +55,7 @@ * http://www.apacheweek.com/features/put */ -static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream) +static size_t read_cb(char *ptr, size_t size, size_t nmemb, void *stream) { size_t retcode; unsigned long nread; @@ -69,8 +76,8 @@ static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream) int main(int argc, char **argv) { CURL *curl; - CURLcode res; - FILE * hd_src; + CURLcode result; + FILE *hd_src; struct stat file_info; char *file; @@ -90,28 +97,23 @@ int main(int argc, char **argv) return 2; /* get the file size of the local file */ -#ifdef UNDER_CE - /* !checksrc! disable BANNEDFUNC 1 */ - if(stat(file, &file_info) != 0) { -#else if(fstat(fileno(hd_src), &file_info) != 0) { -#endif fclose(hd_src); return 1; /* cannot continue */ } /* In Windows, this inits the Winsock stuff */ - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) { + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) { fclose(hd_src); - return (int)res; + return (int)result; } /* get a curl handle */ curl = curl_easy_init(); if(curl) { /* we want to use our own read function */ - curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback); + curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_cb); /* enable uploading (implies PUT over HTTP) */ curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); @@ -129,11 +131,11 @@ int main(int argc, char **argv) (curl_off_t)file_info.st_size); /* Now run off and do what you have been told! */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); @@ -141,5 +143,5 @@ int main(int argc, char **argv) fclose(hd_src); /* close the local file */ curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/https.c b/docs/examples/https.c index 23729afcaa02..7bb11d21e098 100644 --- a/docs/examples/https.c +++ b/docs/examples/https.c @@ -26,15 +26,16 @@ * */ #include + #include int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -56,7 +57,7 @@ int main(void) #ifdef SKIP_HOSTNAME_VERIFICATION /* - * If the site you are connecting to uses a different host name that what + * If the site you are connecting to uses a different hostname than what * they have mentioned in their server certificate's commonName (or * subjectAltName) fields, libcurl refuses to connect. You can skip this * check, but it makes the connection insecure. @@ -67,12 +68,12 @@ int main(void) /* cache the CA cert bundle in memory for a week */ curl_easy_setopt(curl, CURLOPT_CA_CACHE_TIMEOUT, 604800L); - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); @@ -80,5 +81,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/imap-append.c b/docs/examples/imap-append.c index e8851ce97717..7bd75edd9336 100644 --- a/docs/examples/imap-append.c +++ b/docs/examples/imap-append.c @@ -21,14 +21,13 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Send email with IMAP * */ - #include #include + #include /* This is a simple example showing how to send mail using libcurl's IMAP @@ -37,9 +36,9 @@ * Note that this example requires libcurl 7.30.0 or above. */ -#define FROM "" -#define TO "" -#define CC "" +#define FROM "" +#define TO "" +#define CC "" static const char *payload_text = "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n" @@ -59,13 +58,13 @@ struct upload_status { size_t bytes_read; }; -static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp) +static size_t read_cb(char *ptr, size_t size, size_t nmemb, void *userp) { struct upload_status *upload_ctx = (struct upload_status *)userp; const char *data; size_t room = size * nmemb; - if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) { + if((size == 0) || (nmemb == 0) || ((size * nmemb) < 1)) { return 0; } @@ -88,9 +87,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -108,7 +107,7 @@ int main(void) /* In this case, we are using a callback function to specify the data. You * could just use the CURLOPT_READDATA option to specify a FILE pointer to * read from. */ - curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source); + curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_cb); curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx); curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); @@ -118,12 +117,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_INFILESIZE, infilesize); /* Perform the append */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Always cleanup */ curl_easy_cleanup(curl); @@ -131,5 +130,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/imap-authzid.c b/docs/examples/imap-authzid.c index b7c2e43f99d9..bf9a61f6af70 100644 --- a/docs/examples/imap-authzid.c +++ b/docs/examples/imap-authzid.c @@ -21,13 +21,12 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Retrieve emails from a shared IMAP mailbox * */ - #include + #include /* This is a simple example showing how to fetch mail using libcurl's IMAP @@ -40,9 +39,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -61,12 +60,12 @@ int main(void) "imap://imap.example.com/INBOX/;UID=1"); /* Perform the fetch */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Always cleanup */ curl_easy_cleanup(curl); @@ -74,5 +73,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/imap-copy.c b/docs/examples/imap-copy.c index 8adb8b8c6d80..91d95b12a65a 100644 --- a/docs/examples/imap-copy.c +++ b/docs/examples/imap-copy.c @@ -21,13 +21,12 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Copy an email from one IMAP folder to another * */ - #include + #include /* This is a simple example showing how to copy a mail from one mailbox folder @@ -40,9 +39,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -61,12 +60,12 @@ int main(void) * imap-store.c for more information on deleting messages. */ /* Perform the custom request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Always cleanup */ curl_easy_cleanup(curl); @@ -74,5 +73,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/imap-create.c b/docs/examples/imap-create.c index 51fbe5f1420c..259dc2232f7d 100644 --- a/docs/examples/imap-create.c +++ b/docs/examples/imap-create.c @@ -21,13 +21,12 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Create a new IMAP folder * */ - #include + #include /* This is a simple example showing how to create a new mailbox folder using @@ -40,9 +39,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -57,12 +56,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "CREATE FOLDER"); /* Perform the custom request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Always cleanup */ curl_easy_cleanup(curl); @@ -70,5 +69,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/imap-delete.c b/docs/examples/imap-delete.c index a7682f7664d3..03e9d2ad7d48 100644 --- a/docs/examples/imap-delete.c +++ b/docs/examples/imap-delete.c @@ -21,13 +21,12 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Delete an IMAP folder * */ - #include + #include /* This is a simple example showing how to delete an existing mailbox folder @@ -40,9 +39,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -57,12 +56,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE FOLDER"); /* Perform the custom request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Always cleanup */ curl_easy_cleanup(curl); @@ -70,5 +69,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/imap-examine.c b/docs/examples/imap-examine.c index a46d450d21ab..fcb960ce5016 100644 --- a/docs/examples/imap-examine.c +++ b/docs/examples/imap-examine.c @@ -21,13 +21,12 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Obtain information about an IMAP folder * */ - #include + #include /* This is a simple example showing how to obtain information about a mailbox @@ -40,9 +39,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -57,12 +56,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "EXAMINE OUTBOX"); /* Perform the custom request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Always cleanup */ curl_easy_cleanup(curl); @@ -70,5 +69,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/imap-fetch.c b/docs/examples/imap-fetch.c index 937d3e05b80e..b067d1538594 100644 --- a/docs/examples/imap-fetch.c +++ b/docs/examples/imap-fetch.c @@ -21,13 +21,12 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Retrieve IMAP emails * */ - #include + #include /* This is a simple example showing how to fetch mail using libcurl's IMAP @@ -40,9 +39,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -55,12 +54,12 @@ int main(void) "imap://imap.example.com/INBOX/;UID=1"); /* Perform the fetch */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Always cleanup */ curl_easy_cleanup(curl); @@ -68,5 +67,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/imap-list.c b/docs/examples/imap-list.c index 2d882503d09e..263219ededb5 100644 --- a/docs/examples/imap-list.c +++ b/docs/examples/imap-list.c @@ -21,13 +21,12 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * List the folders within an IMAP mailbox * */ - #include + #include /* This is a simple example showing how to list the folders within an IMAP @@ -40,9 +39,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -56,12 +55,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_URL, "imap://imap.example.com"); /* Perform the list */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Always cleanup */ curl_easy_cleanup(curl); @@ -69,5 +68,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/imap-lsub.c b/docs/examples/imap-lsub.c index 74472d42ec23..75dbd3ceaec6 100644 --- a/docs/examples/imap-lsub.c +++ b/docs/examples/imap-lsub.c @@ -21,13 +21,12 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * List the subscribed IMAP folders * */ - #include + #include /* This is a simple example showing how to list the subscribed folders within @@ -40,9 +39,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -58,12 +57,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "LSUB \"\" *"); /* Perform the custom request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Always cleanup */ curl_easy_cleanup(curl); @@ -71,5 +70,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/imap-multi.c b/docs/examples/imap-multi.c index e2d5dd4e9cc6..35aff98ad95b 100644 --- a/docs/examples/imap-multi.c +++ b/docs/examples/imap-multi.c @@ -21,14 +21,13 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Get IMAP email with the multi interface * */ - #include #include + #include /* This is a simple example showing how to fetch mail using libcurl's IMAP @@ -40,16 +39,16 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { - CURLM *mcurl; + CURLM *multi; - mcurl = curl_multi_init(); - if(mcurl) { + multi = curl_multi_init(); + if(multi) { int still_running = 1; /* Set username and password */ @@ -61,22 +60,22 @@ int main(void) "INBOX/;UID=1"); /* Tell the multi stack about our easy handle */ - curl_multi_add_handle(mcurl, curl); + curl_multi_add_handle(multi, curl); do { - CURLMcode mc = curl_multi_perform(mcurl, &still_running); + CURLMcode mresult = curl_multi_perform(multi, &still_running); if(still_running) /* wait for activity, timeout or "nothing" */ - mc = curl_multi_poll(mcurl, NULL, 0, 1000, NULL); + mresult = curl_multi_poll(multi, NULL, 0, 1000, NULL); - if(mc) + if(mresult) break; } while(still_running); /* Always cleanup */ - curl_multi_remove_handle(mcurl, curl); - curl_multi_cleanup(mcurl); + curl_multi_remove_handle(multi, curl); + curl_multi_cleanup(multi); } curl_easy_cleanup(curl); } diff --git a/docs/examples/imap-noop.c b/docs/examples/imap-noop.c index 1d8607590f6f..940724291802 100644 --- a/docs/examples/imap-noop.c +++ b/docs/examples/imap-noop.c @@ -21,13 +21,12 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Perform an IMAP noop * */ - #include + #include /* This is a simple example showing how to perform a noop using libcurl's IMAP @@ -40,9 +39,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -57,12 +56,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "NOOP"); /* Perform the custom request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Always cleanup */ curl_easy_cleanup(curl); @@ -70,5 +69,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/imap-search.c b/docs/examples/imap-search.c index b4e1576b38c6..c548829cb526 100644 --- a/docs/examples/imap-search.c +++ b/docs/examples/imap-search.c @@ -21,13 +21,12 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Search for new IMAP emails * */ - #include + #include /* This is a simple example showing how to search for new messages using @@ -40,9 +39,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -61,12 +60,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "SEARCH NEW"); /* Perform the custom request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Always cleanup */ curl_easy_cleanup(curl); @@ -74,5 +73,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/imap-ssl.c b/docs/examples/imap-ssl.c index 59edd130e526..0ec84d7472a0 100644 --- a/docs/examples/imap-ssl.c +++ b/docs/examples/imap-ssl.c @@ -21,13 +21,12 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * IMAP with implicit SSL * */ - #include + #include /* This is a simple example showing how to fetch mail using libcurl's IMAP @@ -41,9 +40,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -52,7 +51,7 @@ int main(void) curl_easy_setopt(curl, CURLOPT_PASSWORD, "secret"); /* This fetches message 1 from the user's inbox. Note the use of - * imaps:// rather than imap:// to request an SSL based connection. */ + * imaps:// rather than imap:// to request an SSL based connection. */ curl_easy_setopt(curl, CURLOPT_URL, "imaps://imap.example.com/INBOX/;UID=1"); @@ -68,7 +67,7 @@ int main(void) curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); #endif - /* If the site you are connecting to uses a different host name that what + /* If the site you are connecting to uses a different hostname than what * they have mentioned in their server certificate's commonName (or * subjectAltName) fields, libcurl refuses to connect. You can skip this * check, but it makes the connection insecure. */ @@ -82,12 +81,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); /* Perform the fetch */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Always cleanup */ curl_easy_cleanup(curl); @@ -95,5 +94,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/imap-store.c b/docs/examples/imap-store.c index 95d8f0747652..db0310b6b0f0 100644 --- a/docs/examples/imap-store.c +++ b/docs/examples/imap-store.c @@ -21,13 +21,12 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Modify the properties of an email over IMAP * */ - #include + #include /* This is a simple example showing how to modify an existing mail using @@ -40,9 +39,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -59,24 +58,24 @@ int main(void) curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "STORE 1 +Flags \\Deleted"); /* Perform the custom request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); else { /* Set the EXPUNGE command, although you can use the CLOSE command if you * do not want to know the result of the STORE */ curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "EXPUNGE"); /* Perform the second custom request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); } /* Always cleanup */ @@ -85,5 +84,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/imap-tls.c b/docs/examples/imap-tls.c index 9009174ccf01..6c09380221e7 100644 --- a/docs/examples/imap-tls.c +++ b/docs/examples/imap-tls.c @@ -21,13 +21,12 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * IMAP using TLS * */ - #include + #include /* This is a simple example showing how to fetch mail using libcurl's IMAP @@ -41,9 +40,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -82,12 +81,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); /* Perform the fetch */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Always cleanup */ curl_easy_cleanup(curl); @@ -95,5 +94,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/interface.c b/docs/examples/interface.c index 0698b6a8e2f2..cfe3180f5614 100644 --- a/docs/examples/interface.c +++ b/docs/examples/interface.c @@ -26,15 +26,16 @@ * */ #include + #include int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -45,7 +46,7 @@ int main(void) curl_easy_setopt(curl, CURLOPT_INTERFACE, "enp3s0"); curl_easy_setopt(curl, CURLOPT_URL, "https://curl.se/"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* always cleanup */ curl_easy_cleanup(curl); @@ -53,5 +54,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/ipv6.c b/docs/examples/ipv6.c index 1a55d640494f..03e2a0726c23 100644 --- a/docs/examples/ipv6.c +++ b/docs/examples/ipv6.c @@ -26,15 +26,16 @@ * */ #include + #include int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -42,12 +43,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_URL, "https://curl.se/"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/keepalive.c b/docs/examples/keepalive.c index 8d55c7133774..7427673394a7 100644 --- a/docs/examples/keepalive.c +++ b/docs/examples/keepalive.c @@ -26,15 +26,16 @@ * */ #include + #include int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -52,12 +53,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_URL, "https://curl.se/"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/localport.c b/docs/examples/localport.c index 2700457211dd..6cb863cd8dbb 100644 --- a/docs/examples/localport.c +++ b/docs/examples/localport.c @@ -26,15 +26,16 @@ * */ #include + #include int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -46,7 +47,7 @@ int main(void) curl_easy_setopt(curl, CURLOPT_LOCALPORTRANGE, 10L); curl_easy_setopt(curl, CURLOPT_URL, "https://curl.se/"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* always cleanup */ curl_easy_cleanup(curl); @@ -54,5 +55,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/log_failed_transfers.c b/docs/examples/log_failed_transfers.c index fe5f02f882c8..3f651c059b54 100644 --- a/docs/examples/log_failed_transfers.c +++ b/docs/examples/log_failed_transfers.c @@ -31,20 +31,21 @@ * The transfer's log is written to disk only if the transfer fails. * */ +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* for fopen(), strerror(), vsnprintf() */ +#endif +#endif -#ifndef UNDER_CE #include -#endif #include #include #include #include + #include #ifdef _WIN32 -#ifndef _CRT_SECURE_NO_WARNINGS -#define _CRT_SECURE_NO_WARNINGS -#endif #include #define strcasecmp _stricmp #define strncasecmp _strnicmp @@ -130,7 +131,7 @@ static int mem_add(struct mem *mem, const char *str) } #if defined(__GNUC__) || defined(__clang__) -__attribute__ ((format (printf, 2, 3))) +__attribute__((format(printf, 2, 3))) #endif static int mem_addf(struct mem *mem, const char *format, ...) { @@ -140,8 +141,8 @@ static int mem_addf(struct mem *mem, const char *format, ...) /* we need about 100 chars or less to write 95% of lines */ x = 128; - /* first try: there's probably enough memory to write everything. - second try: there's definitely enough memory to write everything. */ + /* first try: there is probably enough memory to write everything. + second try: there is definitely enough memory to write everything. */ for(i = 0; i < 2; ++i) { if(x < 0 || mem_need(mem, (size_t)x + 1) < 0) break; @@ -156,7 +157,7 @@ static int mem_addf(struct mem *mem, const char *format, ...) return x; } -#if defined(_WIN32) && !defined(UNDER_CE) +#ifdef _WIN32 /* Not all versions of Windows CRT vsnprintf are compliant with C99. Some return -1 if buffer too small. Try _vscprintf to get the needed size. */ if(!i && x < 0) { @@ -172,14 +173,14 @@ static int mem_addf(struct mem *mem, const char *format, ...) return -1; } -static int mydebug(CURL *handle, curl_infotype type, +static int mydebug(CURL *curl, curl_infotype type, char *data, size_t size, void *userdata) { struct transfer *t = (struct transfer *)userdata; static const char s_infotype[CURLINFO_END][3] = { "* ", "< ", "> ", "{ ", "} ", "{ ", "} " }; - (void)handle; + (void)curl; switch(type) { case CURLINFO_TEXT: @@ -198,7 +199,7 @@ static int mydebug(CURL *handle, curl_infotype type, return 0; } -static size_t mywrite(char *ptr, size_t size, size_t nmemb, void *userdata) +static size_t write_cb(char *ptr, size_t size, size_t nmemb, void *userdata) { struct transfer *t = (struct transfer *)userdata; @@ -207,7 +208,7 @@ static size_t mywrite(char *ptr, size_t size, size_t nmemb, void *userdata) int main(void) { - CURLcode res; + CURLcode result; unsigned i; int total_failed = 0; char errbuf[CURL_ERROR_SIZE] = { 0, }; @@ -223,10 +224,10 @@ int main(void) transfer[1].bodyfile = "400.txt"; transfer[1].logfile = "400_transfer_log.txt"; - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) { + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) { fprintf(stderr, "curl_global_init failed\n"); - return (int)res; + return (int)result; } /* You could enable global tracing for extra verbosity when verbosity is @@ -235,7 +236,7 @@ int main(void) curl_global_trace("all"); #endif - for(i = 0; i < sizeof(transfer)/sizeof(transfer[0]); ++i) { + for(i = 0; i < sizeof(transfer) / sizeof(transfer[0]); ++i) { int failed = 0; struct transfer *t = &transfer[i]; @@ -258,7 +259,7 @@ int main(void) curl_easy_setopt(t->curl, CURLOPT_DEBUGDATA, t); /* Enable writing the body to a file */ - curl_easy_setopt(t->curl, CURLOPT_WRITEFUNCTION, mywrite); + curl_easy_setopt(t->curl, CURLOPT_WRITEFUNCTION, write_cb); curl_easy_setopt(t->curl, CURLOPT_WRITEDATA, t); /* Enable immediate error on HTTP status codes >= 400 in most cases, @@ -276,7 +277,7 @@ int main(void) if(t->bodyfp) { /* Perform the transfer */ - CURLcode result = curl_easy_perform(t->curl); + result = curl_easy_perform(t->curl); /* Save the body file */ fclose(t->bodyfp); @@ -297,11 +298,9 @@ int main(void) } } else { -#ifndef UNDER_CE mem_addf(&t->log, "Failed to create body output file %s: %s\n", t->bodyfile, strerror(errno)); fprintf(stderr, "%s", t->log.recent); -#endif failed = 1; } @@ -310,12 +309,10 @@ int main(void) if(fp && t->log.len == fwrite(t->log.buf, 1, t->log.len, fp)) fprintf(stderr, "Transfer log written to %s\n", t->logfile); -#ifndef UNDER_CE else { fprintf(stderr, "Failed to write transfer log to %s: %s\n", t->logfile, strerror(errno)); } -#endif if(fp) fclose(fp); diff --git a/docs/examples/maxconnects.c b/docs/examples/maxconnects.c index e89f971cf41e..0efcaeac1cde 100644 --- a/docs/examples/maxconnects.c +++ b/docs/examples/maxconnects.c @@ -26,20 +26,22 @@ * */ #include + #include int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { - const char *urls[] = { "https://example.com", - "https://curl.se", + const char *urls[] = { + "https://example.com/", + "https://curl.se/", "https://www.example/", NULL /* end of list */ }; @@ -54,12 +56,12 @@ int main(void) while(urls[i]) { curl_easy_setopt(curl, CURLOPT_URL, urls[i]); - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); i++; } /* always cleanup */ diff --git a/docs/examples/multi-app.c b/docs/examples/multi-app.c index 7dab0b04f147..44aec5bb2189 100644 --- a/docs/examples/multi-app.c +++ b/docs/examples/multi-app.c @@ -26,11 +26,9 @@ * transfers in parallel. * */ - #include #include -/* curl stuff */ #include /* @@ -38,63 +36,63 @@ */ #define HTTP_HANDLE 0 /* Index for the HTTP transfer */ -#define FTP_HANDLE 1 /* Index for the FTP transfer */ +#define FTP_HANDLE 1 /* Index for the FTP transfer */ #define HANDLECOUNT 2 /* Number of simultaneous transfers */ int main(void) { - CURL *handles[HANDLECOUNT]; - CURLM *multi_handle; + CURL *curl[HANDLECOUNT]; + CURLM *multi; int i; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; /* Allocate one curl handle per transfer */ for(i = 0; i < HANDLECOUNT; i++) - handles[i] = curl_easy_init(); + curl[i] = curl_easy_init(); /* set the options (I left out a few, you get the point anyway) */ - curl_easy_setopt(handles[HTTP_HANDLE], CURLOPT_URL, "https://example.com"); + curl_easy_setopt(curl[HTTP_HANDLE], CURLOPT_URL, "https://example.com"); - curl_easy_setopt(handles[FTP_HANDLE], CURLOPT_URL, "ftp://example.com"); - curl_easy_setopt(handles[FTP_HANDLE], CURLOPT_UPLOAD, 1L); + curl_easy_setopt(curl[FTP_HANDLE], CURLOPT_URL, "ftp://example.com"); + curl_easy_setopt(curl[FTP_HANDLE], CURLOPT_UPLOAD, 1L); /* init a multi stack */ - multi_handle = curl_multi_init(); - if(multi_handle) { + multi = curl_multi_init(); + if(multi) { int still_running = 1; /* keep number of running handles */ - CURLMsg *msg; /* for picking up messages with the transfer status */ + CURLMsg *msg; /* for picking up messages with the transfer status */ int msgs_left; /* how many messages are left */ /* add the individual transfers */ for(i = 0; i < HANDLECOUNT; i++) - curl_multi_add_handle(multi_handle, handles[i]); + curl_multi_add_handle(multi, curl[i]); while(still_running) { - CURLMcode mc = curl_multi_perform(multi_handle, &still_running); + CURLMcode mresult = curl_multi_perform(multi, &still_running); if(still_running) /* wait for activity, timeout or "nothing" */ - mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL); + mresult = curl_multi_poll(multi, NULL, 0, 1000, NULL); - if(mc) + if(mresult) break; } /* See how the transfers went */ /* !checksrc! disable EQUALSNULL 1 */ - while((msg = curl_multi_info_read(multi_handle, &msgs_left)) != NULL) { + while((msg = curl_multi_info_read(multi, &msgs_left)) != NULL) { if(msg->msg == CURLMSG_DONE) { int idx; /* Find out which handle this message is about */ for(idx = 0; idx < HANDLECOUNT; idx++) { - int found = (msg->easy_handle == handles[idx]); + int found = (msg->easy_handle == curl[idx]); if(found) break; } @@ -112,14 +110,14 @@ int main(void) /* remove the transfers */ for(i = 0; i < HANDLECOUNT; i++) - curl_multi_remove_handle(multi_handle, handles[i]); + curl_multi_remove_handle(multi, curl[i]); - curl_multi_cleanup(multi_handle); + curl_multi_cleanup(multi); } /* Free the curl handles */ for(i = 0; i < HANDLECOUNT; i++) - curl_easy_cleanup(handles[i]); + curl_easy_cleanup(curl[i]); curl_global_cleanup(); diff --git a/docs/examples/multi-debugcallback.c b/docs/examples/multi-debugcallback.c index 278a5b4a2e1e..3798f541b233 100644 --- a/docs/examples/multi-debugcallback.c +++ b/docs/examples/multi-debugcallback.c @@ -25,16 +25,14 @@ * multi interface and debug callback * */ - #include #include -/* curl stuff */ #include #define TRUE 1 -static void dump(const char *text, FILE *stream, unsigned char *ptr, +static void dump(const char *text, FILE *stream, const unsigned char *ptr, size_t size, char nohex) { size_t i; @@ -71,7 +69,7 @@ static void dump(const char *text, FILE *stream, unsigned char *ptr, } fprintf(stream, "%c", (ptr[i + c] >= 0x20) && (ptr[i + c] < 0x80) ? ptr[i + c] : '.'); - /* check again for 0D0A, to avoid an extra \n if it's at width */ + /* check again for 0D0A, to avoid an extra \n if it is at width */ if(nohex && (i + c + 2 < size) && ptr[i + c + 1] == 0x0D && ptr[i + c + 2] == 0x0A) { i += (c + 3 - width); @@ -83,14 +81,14 @@ static void dump(const char *text, FILE *stream, unsigned char *ptr, fflush(stream); } -static int my_trace(CURL *handle, curl_infotype type, +static int my_trace(CURL *curl, curl_infotype type, unsigned char *data, size_t size, void *userp) { const char *text; (void)userp; - (void)handle; + (void)curl; switch(type) { case CURLINFO_TEXT: @@ -121,48 +119,48 @@ static int my_trace(CURL *handle, curl_infotype type, */ int main(void) { - CURL *http_handle; + CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; - http_handle = curl_easy_init(); - if(http_handle) { + curl = curl_easy_init(); + if(curl) { - CURLM *multi_handle; + CURLM *multi; /* set the options (I left out a few, you get the point anyway) */ - curl_easy_setopt(http_handle, CURLOPT_URL, "https://www.example.com/"); + curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/"); - curl_easy_setopt(http_handle, CURLOPT_DEBUGFUNCTION, my_trace); - curl_easy_setopt(http_handle, CURLOPT_VERBOSE, 1L); + curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, my_trace); + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); /* init a multi stack */ - multi_handle = curl_multi_init(); - if(multi_handle) { + multi = curl_multi_init(); + if(multi) { int still_running = 0; /* keep number of running handles */ /* add the individual transfers */ - curl_multi_add_handle(multi_handle, http_handle); + curl_multi_add_handle(multi, curl); do { - CURLMcode mc = curl_multi_perform(multi_handle, &still_running); + CURLMcode mresult = curl_multi_perform(multi, &still_running); if(still_running) /* wait for activity, timeout or "nothing" */ - mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL); + mresult = curl_multi_poll(multi, NULL, 0, 1000, NULL); - if(mc) + if(mresult) break; } while(still_running); - curl_multi_cleanup(multi_handle); + curl_multi_cleanup(multi); } - curl_easy_cleanup(http_handle); + curl_easy_cleanup(curl); } curl_global_cleanup(); diff --git a/docs/examples/multi-double.c b/docs/examples/multi-double.c index 71ac7422d6d2..04ea342ed8e6 100644 --- a/docs/examples/multi-double.c +++ b/docs/examples/multi-double.c @@ -28,7 +28,6 @@ #include #include -/* curl stuff */ #include /* @@ -36,52 +35,51 @@ */ int main(void) { - CURL *http_handle; - CURL *http_handle2; + CURL *curl; + CURL *curl2; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; - http_handle = curl_easy_init(); - http_handle2 = curl_easy_init(); + curl = curl_easy_init(); + curl2 = curl_easy_init(); - if(http_handle && - http_handle2) { + if(curl && curl2) { - CURLM *multi_handle; + CURLM *multi; /* set options */ - curl_easy_setopt(http_handle, CURLOPT_URL, "https://www.example.com/"); + curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/"); /* set options */ - curl_easy_setopt(http_handle2, CURLOPT_URL, "http://localhost/"); + curl_easy_setopt(curl2, CURLOPT_URL, "http://localhost/"); /* init a multi stack */ - multi_handle = curl_multi_init(); - if(multi_handle) { + multi = curl_multi_init(); + if(multi) { int still_running = 1; /* keep number of running handles */ /* add the individual transfers */ - curl_multi_add_handle(multi_handle, http_handle); - curl_multi_add_handle(multi_handle, http_handle2); + curl_multi_add_handle(multi, curl); + curl_multi_add_handle(multi, curl2); while(still_running) { CURLMsg *msg; int queued; - CURLMcode mc = curl_multi_perform(multi_handle, &still_running); + CURLMcode mresult = curl_multi_perform(multi, &still_running); if(still_running) /* wait for activity, timeout or "nothing" */ - mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL); + mresult = curl_multi_poll(multi, NULL, 0, 1000, NULL); - if(mc) + if(mresult) break; do { - msg = curl_multi_info_read(multi_handle, &queued); + msg = curl_multi_info_read(multi, &queued); if(msg) { if(msg->msg == CURLMSG_DONE) { /* a transfer ended */ @@ -91,15 +89,15 @@ int main(void) } while(msg); } - curl_multi_remove_handle(multi_handle, http_handle); - curl_multi_remove_handle(multi_handle, http_handle2); + curl_multi_remove_handle(multi, curl); + curl_multi_remove_handle(multi, curl2); - curl_multi_cleanup(multi_handle); + curl_multi_cleanup(multi); } } - curl_easy_cleanup(http_handle); - curl_easy_cleanup(http_handle2); + curl_easy_cleanup(curl); + curl_easy_cleanup(curl2); curl_global_cleanup(); diff --git a/docs/examples/multi-event.c b/docs/examples/multi-event.c index af77101b638a..b4e7b18083d6 100644 --- a/docs/examples/multi-event.c +++ b/docs/examples/multi-event.c @@ -21,19 +21,19 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * multi_socket API using libevent * */ - #include #include + #include + #include static struct event_base *base; -static CURLM *curl_handle; +static CURLM *multi; static struct event *timeout; struct curl_context { @@ -47,7 +47,7 @@ static struct curl_context *create_curl_context(curl_socket_t sockfd) { struct curl_context *context; - context = (struct curl_context *) malloc(sizeof(*context)); + context = (struct curl_context *)malloc(sizeof(*context)); context->sockfd = sockfd; @@ -67,7 +67,7 @@ static void add_download(const char *url, int num) { char filename[50]; FILE *file; - CURL *handle; + CURL *curl; snprintf(filename, sizeof(filename), "%d.download", num); @@ -77,11 +77,11 @@ static void add_download(const char *url, int num) return; } - handle = curl_easy_init(); - curl_easy_setopt(handle, CURLOPT_WRITEDATA, file); - curl_easy_setopt(handle, CURLOPT_PRIVATE, file); - curl_easy_setopt(handle, CURLOPT_URL, url); - curl_multi_add_handle(curl_handle, handle); + curl = curl_easy_init(); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, file); + curl_easy_setopt(curl, CURLOPT_PRIVATE, file); + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_multi_add_handle(multi, curl); fprintf(stderr, "Added download %s -> %s\n", url, filename); } @@ -90,10 +90,10 @@ static void check_multi_info(void) char *done_url; CURLMsg *message; int pending; - CURL *easy_handle; + CURL *curl; FILE *file; - while((message = curl_multi_info_read(curl_handle, &pending))) { + while((message = curl_multi_info_read(multi, &pending))) { switch(message->msg) { case CURLMSG_DONE: /* Do not use message data after calling curl_multi_remove_handle() and @@ -101,14 +101,14 @@ static void check_multi_info(void) "WARNING: The data the returned pointer points to does not survive calling curl_multi_cleanup, curl_multi_remove_handle or curl_easy_cleanup." */ - easy_handle = message->easy_handle; + curl = message->easy_handle; - curl_easy_getinfo(easy_handle, CURLINFO_EFFECTIVE_URL, &done_url); - curl_easy_getinfo(easy_handle, CURLINFO_PRIVATE, &file); + curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &done_url); + curl_easy_getinfo(curl, CURLINFO_PRIVATE, &file); printf("%s DONE\n", done_url); - curl_multi_remove_handle(curl_handle, easy_handle); - curl_easy_cleanup(easy_handle); + curl_multi_remove_handle(multi, curl); + curl_easy_cleanup(curl); if(file) { fclose(file); } @@ -134,10 +134,9 @@ static void curl_perform(int fd, short event, void *arg) if(event & EV_WRITE) flags |= CURL_CSELECT_OUT; - context = (struct curl_context *) arg; + context = (struct curl_context *)arg; - curl_multi_socket_action(curl_handle, context->sockfd, flags, - &running_handles); + curl_multi_socket_action(multi, context->sockfd, flags, &running_handles); check_multi_info(); } @@ -148,8 +147,7 @@ static void on_timeout(evutil_socket_t fd, short events, void *arg) (void)fd; (void)events; (void)arg; - curl_multi_socket_action(curl_handle, CURL_SOCKET_TIMEOUT, 0, - &running_handles); + curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0, &running_handles); check_multi_info(); } @@ -172,23 +170,23 @@ static int start_timeout(CURLM *multi, long timeout_ms, void *userp) return 0; } -static int handle_socket(CURL *easy, curl_socket_t s, int action, void *userp, +static int handle_socket(CURL *curl, curl_socket_t s, int action, void *userp, void *socketp) { struct curl_context *curl_context; int events = 0; - (void)easy; + (void)curl; (void)userp; switch(action) { case CURL_POLL_IN: case CURL_POLL_OUT: case CURL_POLL_INOUT: - curl_context = socketp ? - (struct curl_context *) socketp : create_curl_context(s); + curl_context = + socketp ? (struct curl_context *)socketp : create_curl_context(s); - curl_multi_assign(curl_handle, s, (void *) curl_context); + curl_multi_assign(multi, s, (void *)curl_context); if(action != CURL_POLL_IN) events |= EV_WRITE; @@ -199,15 +197,15 @@ static int handle_socket(CURL *easy, curl_socket_t s, int action, void *userp, event_del(curl_context->event); event_assign(curl_context->event, base, curl_context->sockfd, - (short)events, curl_perform, curl_context); + (short)events, curl_perform, curl_context); event_add(curl_context->event, NULL); break; case CURL_POLL_REMOVE: if(socketp) { - event_del(((struct curl_context*) socketp)->event); - destroy_curl_context((struct curl_context*) socketp); - curl_multi_assign(curl_handle, s, NULL); + event_del(((struct curl_context *)socketp)->event); + destroy_curl_context((struct curl_context *)socketp); + curl_multi_assign(multi, s, NULL); } break; default: @@ -219,24 +217,24 @@ static int handle_socket(CURL *easy, curl_socket_t s, int action, void *userp, int main(int argc, char **argv) { - CURLcode res; + CURLcode result; if(argc <= 1) return 0; - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) { + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) { fprintf(stderr, "Could not init curl\n"); - return (int)res; + return (int)result; } base = event_base_new(); timeout = evtimer_new(base, on_timeout, NULL); - curl_handle = curl_multi_init(); - if(curl_handle) { - curl_multi_setopt(curl_handle, CURLMOPT_SOCKETFUNCTION, handle_socket); - curl_multi_setopt(curl_handle, CURLMOPT_TIMERFUNCTION, start_timeout); + multi = curl_multi_init(); + if(multi) { + curl_multi_setopt(multi, CURLMOPT_SOCKETFUNCTION, handle_socket); + curl_multi_setopt(multi, CURLMOPT_TIMERFUNCTION, start_timeout); while(argc-- > 1) { add_download(argv[argc], argc); @@ -244,7 +242,7 @@ int main(int argc, char **argv) event_base_dispatch(base); - curl_multi_cleanup(curl_handle); + curl_multi_cleanup(multi); } event_free(timeout); event_base_free(base); diff --git a/docs/examples/multi-formadd.c b/docs/examples/multi-formadd.c index 08d852ec6528..6611f2f12e0c 100644 --- a/docs/examples/multi-formadd.c +++ b/docs/examples/multi-formadd.c @@ -25,12 +25,10 @@ * using the multi interface to do a multipart formpost without blocking * */ - /* - * Warning: this example uses the deprecated form api. See "multi-post.c" - * for a similar example using the mime api. + * Warning: this example uses the deprecated form API. See "multi-post.c" + * for a similar example using the mime API. */ - #include #include @@ -45,13 +43,13 @@ int main(void) struct curl_slist *headerlist = NULL; static const char buf[] = "Expect:"; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; CURL_IGNORE_DEPRECATION( /* Fill in the file upload field. This makes libcurl load data from - the given file name when curl_easy_perform() is called. */ + the given filename when curl_easy_perform() is called. */ curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "sendfile", @@ -79,10 +77,10 @@ int main(void) curl = curl_easy_init(); if(curl) { - CURLM *multi_handle; + CURLM *multi; - multi_handle = curl_multi_init(); - if(multi_handle) { + multi = curl_multi_init(); + if(multi) { int still_running = 0; @@ -96,21 +94,21 @@ int main(void) curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); ) - curl_multi_add_handle(multi_handle, curl); + curl_multi_add_handle(multi, curl); do { - CURLMcode mc = curl_multi_perform(multi_handle, &still_running); + CURLMcode mresult = curl_multi_perform(multi, &still_running); if(still_running) /* wait for activity, timeout or "nothing" */ - mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL); + mresult = curl_multi_poll(multi, NULL, 0, 1000, NULL); - if(mc) + if(mresult) break; } while(still_running); - curl_multi_cleanup(multi_handle); + curl_multi_cleanup(multi); } /* always cleanup */ diff --git a/docs/examples/multi-legacy.c b/docs/examples/multi-legacy.c index 19821ad6d327..1c14ea0bd0ec 100644 --- a/docs/examples/multi-legacy.c +++ b/docs/examples/multi-legacy.c @@ -26,7 +26,6 @@ * transfers in parallel without curl_multi_wait/poll. * */ - #include #include @@ -36,59 +35,58 @@ #include #endif -/* curl stuff */ #include /* * Download an HTTP file and upload an FTP file simultaneously. */ -#define HTTP_HANDLE 0 /* Index for the HTTP transfer */ -#define FTP_HANDLE 1 /* Index for the FTP transfer */ -#define HANDLECOUNT 2 /* Number of simultaneous transfers */ +#define HTTP_HANDLE 0 /* Index for the HTTP transfer */ +#define FTP_HANDLE 1 /* Index for the FTP transfer */ +#define HANDLECOUNT 2 /* Number of simultaneous transfers */ int main(void) { - CURL *handles[HANDLECOUNT]; - CURLM *multi_handle; + CURL *curl[HANDLECOUNT]; + CURLM *multi; int i; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; /* Allocate one curl handle per transfer */ for(i = 0; i < HANDLECOUNT; i++) - handles[i] = curl_easy_init(); + curl[i] = curl_easy_init(); /* set the options (I left out a few, you get the point anyway) */ - curl_easy_setopt(handles[HTTP_HANDLE], CURLOPT_URL, "https://example.com"); + curl_easy_setopt(curl[HTTP_HANDLE], CURLOPT_URL, "https://example.com"); - curl_easy_setopt(handles[FTP_HANDLE], CURLOPT_URL, "ftp://example.com"); - curl_easy_setopt(handles[FTP_HANDLE], CURLOPT_UPLOAD, 1L); + curl_easy_setopt(curl[FTP_HANDLE], CURLOPT_URL, "ftp://example.com"); + curl_easy_setopt(curl[FTP_HANDLE], CURLOPT_UPLOAD, 1L); /* init a multi stack */ - multi_handle = curl_multi_init(); - if(multi_handle) { + multi = curl_multi_init(); + if(multi) { int still_running = 0; /* keep number of running handles */ - CURLMsg *msg; /* for picking up messages with the transfer status */ + CURLMsg *msg; /* for picking up messages with the transfer status */ int msgs_left; /* how many messages are left */ /* add the individual transfers */ for(i = 0; i < HANDLECOUNT; i++) - curl_multi_add_handle(multi_handle, handles[i]); + curl_multi_add_handle(multi, curl[i]); /* we start some action by calling perform right away */ - curl_multi_perform(multi_handle, &still_running); + curl_multi_perform(multi, &still_running); while(still_running) { struct timeval timeout; - int rc; /* select() return code */ - CURLMcode mc; /* curl_multi_fdset() return code */ + int rc; /* select() return code */ + CURLMcode mresult; /* curl_multi_fdset() return code */ fd_set fdread; fd_set fdwrite; @@ -105,7 +103,7 @@ int main(void) timeout.tv_sec = 1; timeout.tv_usec = 0; - curl_multi_timeout(multi_handle, &curl_timeo); + curl_multi_timeout(multi, &curl_timeo); if(curl_timeo >= 0) { #if defined(MSDOS) || defined(__AMIGA__) timeout.tv_sec = (time_t)(curl_timeo / 1000); @@ -123,10 +121,10 @@ int main(void) } /* get file descriptors from the transfers */ - mc = curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd); + mresult = curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd); - if(mc != CURLM_OK) { - fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc); + if(mresult != CURLM_OK) { + fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mresult); break; } @@ -142,7 +140,7 @@ int main(void) rc = 0; #else /* Portable sleep for platforms other than Windows. */ - struct timeval wait = {0}; + struct timeval wait = { 0 }; wait.tv_usec = 100 * 1000; /* 100ms */ rc = select(0, NULL, NULL, NULL, &wait); #endif @@ -159,20 +157,20 @@ int main(void) break; case 0: /* timeout */ default: /* action */ - curl_multi_perform(multi_handle, &still_running); + curl_multi_perform(multi, &still_running); break; } } /* See how the transfers went */ /* !checksrc! disable EQUALSNULL 1 */ - while((msg = curl_multi_info_read(multi_handle, &msgs_left)) != NULL) { + while((msg = curl_multi_info_read(multi, &msgs_left)) != NULL) { if(msg->msg == CURLMSG_DONE) { int idx; /* Find out which handle this message is about */ for(idx = 0; idx < HANDLECOUNT; idx++) { - int found = (msg->easy_handle == handles[idx]); + int found = (msg->easy_handle == curl[idx]); if(found) break; } @@ -188,12 +186,12 @@ int main(void) } } - curl_multi_cleanup(multi_handle); + curl_multi_cleanup(multi); } /* Free the curl handles */ for(i = 0; i < HANDLECOUNT; i++) - curl_easy_cleanup(handles[i]); + curl_easy_cleanup(curl[i]); curl_global_cleanup(); diff --git a/docs/examples/multi-post.c b/docs/examples/multi-post.c index ac7d2f525205..48db32ff394e 100644 --- a/docs/examples/multi-post.c +++ b/docs/examples/multi-post.c @@ -25,7 +25,6 @@ * using the multi interface to do a multipart formpost without blocking * */ - #include #include @@ -40,16 +39,16 @@ int main(void) CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { - CURLM *multi_handle; + CURLM *multi; - multi_handle = curl_multi_init(); - if(multi_handle) { + multi = curl_multi_init(); + if(multi) { int still_running = 0; /* Create the form */ @@ -82,20 +81,20 @@ int main(void) curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist); curl_easy_setopt(curl, CURLOPT_MIMEPOST, form); - curl_multi_add_handle(multi_handle, curl); + curl_multi_add_handle(multi, curl); do { - CURLMcode mc = curl_multi_perform(multi_handle, &still_running); + CURLMcode mresult = curl_multi_perform(multi, &still_running); if(still_running) /* wait for activity, timeout or "nothing" */ - mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL); + mresult = curl_multi_poll(multi, NULL, 0, 1000, NULL); - if(mc) + if(mresult) break; } while(still_running); - curl_multi_cleanup(multi_handle); + curl_multi_cleanup(multi); } /* always cleanup */ diff --git a/docs/examples/multi-single.c b/docs/examples/multi-single.c index 50736c720112..0cf18891fd78 100644 --- a/docs/examples/multi-single.c +++ b/docs/examples/multi-single.c @@ -29,7 +29,6 @@ #include #include -/* curl stuff */ #include /* @@ -37,48 +36,49 @@ */ int main(void) { - CURL *http_handle; + CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; - http_handle = curl_easy_init(); - if(http_handle) { + curl = curl_easy_init(); + if(curl) { - CURLM *multi_handle; + CURLM *multi; int still_running = 1; /* keep number of running handles */ /* set the options (I left out a few, you get the point anyway) */ - curl_easy_setopt(http_handle, CURLOPT_URL, "https://www.example.com/"); + curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/"); /* init a multi stack */ - multi_handle = curl_multi_init(); - if(multi_handle) { + multi = curl_multi_init(); + if(multi) { /* add the individual transfers */ - curl_multi_add_handle(multi_handle, http_handle); + curl_multi_add_handle(multi, curl); do { - CURLMcode mc = curl_multi_perform(multi_handle, &still_running); + CURLMcode mresult = curl_multi_perform(multi, &still_running); - if(!mc) + if(!mresult) /* wait for activity, timeout or "nothing" */ - mc = curl_multi_poll(multi_handle, NULL, 0, 1000, NULL); + mresult = curl_multi_poll(multi, NULL, 0, 1000, NULL); - if(mc) { - fprintf(stderr, "curl_multi_poll() failed, code %d.\n", (int)mc); + if(mresult) { + fprintf(stderr, "curl_multi_poll() failed, code %d.\n", + (int)mresult); break; } } while(still_running); - curl_multi_remove_handle(multi_handle, http_handle); + curl_multi_remove_handle(multi, curl); - curl_multi_cleanup(multi_handle); + curl_multi_cleanup(multi); } - curl_easy_cleanup(http_handle); + curl_easy_cleanup(curl); } curl_global_cleanup(); diff --git a/docs/examples/multi-uv.c b/docs/examples/multi-uv.c index d2f18348e68a..dd0102c264c3 100644 --- a/docs/examples/multi-uv.c +++ b/docs/examples/multi-uv.c @@ -25,7 +25,6 @@ * multi_socket API using libuv * */ - /* Use the socket_action interface to download multiple files in parallel, powered by libuv. @@ -38,7 +37,9 @@ #include #include + #include + #include /* object to pass to the callbacks */ @@ -59,7 +60,7 @@ static struct curl_context *create_curl_context(curl_socket_t sockfd, { struct curl_context *context; - context = (struct curl_context *) malloc(sizeof(*context)); + context = (struct curl_context *)malloc(sizeof(*context)); context->sockfd = sockfd; context->uv = uv; @@ -72,20 +73,20 @@ static struct curl_context *create_curl_context(curl_socket_t sockfd, static void curl_close_cb(uv_handle_t *handle) { - struct curl_context *context = (struct curl_context *) handle->data; + struct curl_context *context = (struct curl_context *)handle->data; free(context); } static void destroy_curl_context(struct curl_context *context) { - uv_close((uv_handle_t *) &context->poll_handle, curl_close_cb); + uv_close((uv_handle_t *)&context->poll_handle, curl_close_cb); } static void add_download(const char *url, int num, CURLM *multi) { char filename[50]; FILE *file; - CURL *handle; + CURL *curl; snprintf(filename, sizeof(filename), "%d.download", num); @@ -95,23 +96,23 @@ static void add_download(const char *url, int num, CURLM *multi) return; } - handle = curl_easy_init(); - curl_easy_setopt(handle, CURLOPT_WRITEDATA, file); - curl_easy_setopt(handle, CURLOPT_PRIVATE, file); - curl_easy_setopt(handle, CURLOPT_URL, url); - curl_multi_add_handle(multi, handle); + curl = curl_easy_init(); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, file); + curl_easy_setopt(curl, CURLOPT_PRIVATE, file); + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_multi_add_handle(multi, curl); fprintf(stderr, "Added download %s -> %s\n", url, filename); } -static void check_multi_info(struct curl_context *context) +static void check_multi_info(struct datauv *uv) { char *done_url; CURLMsg *message; int pending; - CURL *easy_handle; + CURL *curl; FILE *file; - while((message = curl_multi_info_read(context->uv->multi, &pending))) { + while((message = curl_multi_info_read(uv->multi, &pending))) { switch(message->msg) { case CURLMSG_DONE: /* Do not use message data after calling curl_multi_remove_handle() and @@ -119,14 +120,14 @@ static void check_multi_info(struct curl_context *context) "WARNING: The data the returned pointer points to does not survive calling curl_multi_cleanup, curl_multi_remove_handle or curl_easy_cleanup." */ - easy_handle = message->easy_handle; + curl = message->easy_handle; - curl_easy_getinfo(easy_handle, CURLINFO_EFFECTIVE_URL, &done_url); - curl_easy_getinfo(easy_handle, CURLINFO_PRIVATE, &file); + curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &done_url); + curl_easy_getinfo(curl, CURLINFO_PRIVATE, &file); printf("%s DONE\n", done_url); - curl_multi_remove_handle(context->uv->multi, easy_handle); - curl_easy_cleanup(easy_handle); + curl_multi_remove_handle(uv->multi, curl); + curl_easy_cleanup(curl); if(file) { fclose(file); } @@ -144,7 +145,7 @@ static void on_uv_socket(uv_poll_t *req, int status, int events) { int running_handles; int flags = 0; - struct curl_context *context = (struct curl_context *) req->data; + struct curl_context *context = (struct curl_context *)req->data; (void)status; if(events & UV_READABLE) flags |= CURL_CSELECT_IN; @@ -153,19 +154,21 @@ static void on_uv_socket(uv_poll_t *req, int status, int events) curl_multi_socket_action(context->uv->multi, context->sockfd, flags, &running_handles); - check_multi_info(context); + check_multi_info(context->uv); } /* callback from libuv when timeout expires */ static void on_uv_timeout(uv_timer_t *req) { - struct curl_context *context = (struct curl_context *) req->data; - if(context) { - int running_handles; - curl_multi_socket_action(context->uv->multi, CURL_SOCKET_TIMEOUT, 0, - &running_handles); - check_multi_info(context); - } + /* get the datauv struct from the timer handle */ + struct datauv *uv = (struct datauv *)req; + int running_handles; + + curl_multi_socket_action(uv->multi, CURL_SOCKET_TIMEOUT, 0, + &running_handles); + + if(running_handles) + check_multi_info(uv); } /* callback from libcurl to update the timeout expiry */ @@ -186,22 +189,22 @@ static int cb_timeout(CURLM *multi, long timeout_ms, void *userp) } /* callback from libcurl to update socket activity to wait for */ -static int cb_socket(CURL *easy, curl_socket_t s, int action, +static int cb_socket(CURL *curl, curl_socket_t s, int action, void *userp, void *socketp) { struct datauv *uv = (struct datauv *)userp; struct curl_context *curl_context; int events = 0; - (void)easy; + (void)curl; switch(action) { case CURL_POLL_IN: case CURL_POLL_OUT: case CURL_POLL_INOUT: - curl_context = socketp ? - (struct curl_context *) socketp : create_curl_context(s, uv); + curl_context = + socketp ? (struct curl_context *)socketp : create_curl_context(s, uv); - curl_multi_assign(uv->multi, s, (void *) curl_context); + curl_multi_assign(uv->multi, s, (void *)curl_context); if(action != CURL_POLL_IN) events |= UV_WRITABLE; @@ -212,8 +215,8 @@ static int cb_socket(CURL *easy, curl_socket_t s, int action, break; case CURL_POLL_REMOVE: if(socketp) { - uv_poll_stop(&((struct curl_context*)socketp)->poll_handle); - destroy_curl_context((struct curl_context*) socketp); + uv_poll_stop(&((struct curl_context *)socketp)->poll_handle); + destroy_curl_context((struct curl_context *)socketp); curl_multi_assign(uv->multi, s, NULL); } break; @@ -226,16 +229,16 @@ static int cb_socket(CURL *easy, curl_socket_t s, int action, int main(int argc, char **argv) { - CURLcode res; + CURLcode result; struct datauv uv = { 0 }; int running_handles; if(argc <= 1) return 0; - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; uv.loop = uv_default_loop(); uv_timer_init(uv.loop, &uv.timeout); diff --git a/docs/examples/multithread.c b/docs/examples/multithread.c deleted file mode 100644 index 36836ef47533..000000000000 --- a/docs/examples/multithread.c +++ /dev/null @@ -1,104 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at https://curl.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the 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 multi-threaded program using pthreads to fetch several files at once - * - */ - -/* Requires: HAVE_PTHREAD_H */ - -#include -#include -#include - -#define NUMT 4 - -/* - List of URLs to fetch. - - If you intend to use an SSL-based protocol here you might need to setup TLS - library mutex callbacks as described here: - - https://curl.se/libcurl/c/threadsafe.html - -*/ -static const char * const urls[NUMT]= { - "https://curl.se/", - "ftp://example.com/", - "https://example.net/", - "www.example" -}; - -static void *pull_one_url(void *pindex) -{ - CURL *curl; - - curl = curl_easy_init(); - if(curl) { - int i = *(int *)pindex; - curl_easy_setopt(curl, CURLOPT_URL, urls[i]); - (void)curl_easy_perform(curl); /* ignores error */ - curl_easy_cleanup(curl); - } - - return NULL; -} - - -/* - int pthread_create(pthread_t *new_thread_ID, - const pthread_attr_t *attr, - void * (*start_func)(void *), void *arg); -*/ - -int main(void) -{ - CURLcode res; - pthread_t tid[NUMT]; - int i; - - /* Must initialize libcurl before any threads are started */ - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; - - for(i = 0; i < NUMT; i++) { - int error = pthread_create(&tid[i], - NULL, /* default attributes please */ - pull_one_url, - (void *)&i); - if(error) - fprintf(stderr, "Couldn't run thread number %d, errno %d\n", i, error); - else - fprintf(stderr, "Thread %d, gets %s\n", i, urls[i]); - } - - /* now wait for all threads to terminate */ - for(i = 0; i < NUMT; i++) { - pthread_join(tid[i], NULL); - fprintf(stderr, "Thread %d terminated\n", i); - } - curl_global_cleanup(); - return 0; -} diff --git a/docs/examples/netrc.c b/docs/examples/netrc.c index 148a7e422be9..8bc998ae4396 100644 --- a/docs/examples/netrc.c +++ b/docs/examples/netrc.c @@ -26,29 +26,29 @@ * */ #include + #include int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; 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_NETRC_FILE, "/home/daniel/s3cr3ts.txt"); curl_easy_setopt(curl, CURLOPT_URL, "https://curl.se/"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/parseurl.c b/docs/examples/parseurl.c index 8675adc62383..f70df19bef2f 100644 --- a/docs/examples/parseurl.c +++ b/docs/examples/parseurl.c @@ -26,6 +26,7 @@ * */ #include + #include #if !CURL_AT_LEAST_VERSION(7, 62, 0) @@ -51,7 +52,7 @@ int main(void) /* extract hostname from the parsed URL */ uc = curl_url_get(h, CURLUPART_HOST, &host, 0); if(!uc) { - printf("Host name: %s\n", host); + printf("Hostname: %s\n", host); curl_free(host); } diff --git a/docs/examples/persistent.c b/docs/examples/persistent.c index 7cde055d69b8..50d110f3e0f1 100644 --- a/docs/examples/persistent.c +++ b/docs/examples/persistent.c @@ -33,9 +33,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -45,23 +45,23 @@ int main(void) /* get the first document */ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* get another document from the same server using the same connection */ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/docs/"); - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); @@ -69,5 +69,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/pop3-authzid.c b/docs/examples/pop3-authzid.c index 8cfe80bca239..ed7993d85fa5 100644 --- a/docs/examples/pop3-authzid.c +++ b/docs/examples/pop3-authzid.c @@ -21,13 +21,12 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Retrieve emails from a shared POP3 mailbox * */ - #include + #include /* This is a simple example showing how to retrieve mail using libcurl's POP3 @@ -40,9 +39,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -60,12 +59,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_URL, "pop3://pop.example.com/1"); /* Perform the retr */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Always cleanup */ curl_easy_cleanup(curl); @@ -73,5 +72,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/pop3-dele.c b/docs/examples/pop3-dele.c index 84592da4f9ff..f872b882e4f8 100644 --- a/docs/examples/pop3-dele.c +++ b/docs/examples/pop3-dele.c @@ -21,13 +21,12 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Delete POP3 emails * */ - #include + #include /* This is a simple example showing how to delete an existing mail using @@ -40,9 +39,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -60,12 +59,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_NOBODY, 1L); /* Perform the custom request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Always cleanup */ curl_easy_cleanup(curl); @@ -73,5 +72,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/pop3-list.c b/docs/examples/pop3-list.c index 05ecc662331a..7cc9a249d5a0 100644 --- a/docs/examples/pop3-list.c +++ b/docs/examples/pop3-list.c @@ -21,13 +21,12 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * List the contents of a POP3 mailbox * */ - #include + #include /* This is a simple example using libcurl's POP3 capabilities to list the @@ -40,9 +39,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -54,12 +53,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_URL, "pop3://pop.example.com"); /* Perform the list */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Always cleanup */ curl_easy_cleanup(curl); @@ -67,5 +66,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/pop3-multi.c b/docs/examples/pop3-multi.c index 4d418a7d09a7..741b7f8d2d72 100644 --- a/docs/examples/pop3-multi.c +++ b/docs/examples/pop3-multi.c @@ -21,14 +21,13 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Get POP3 email using the multi interface * */ - #include #include + #include /* This is a simple example showing how to retrieve mail using libcurl's POP3 @@ -38,19 +37,19 @@ int main(void) { - CURLcode res; + CURLcode result; CURL *curl; - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { - CURLM *mcurl; + CURLM *multi; - mcurl = curl_multi_init(); - if(mcurl) { + multi = curl_multi_init(); + if(multi) { int still_running = 1; /* Set username and password */ @@ -61,23 +60,23 @@ int main(void) curl_easy_setopt(curl, CURLOPT_URL, "pop3://pop.example.com/1"); /* Tell the multi stack about our easy handle */ - curl_multi_add_handle(mcurl, curl); + curl_multi_add_handle(multi, curl); do { - CURLMcode mc = curl_multi_perform(mcurl, &still_running); + CURLMcode mresult = curl_multi_perform(multi, &still_running); if(still_running) /* wait for activity, timeout or "nothing" */ - mc = curl_multi_poll(mcurl, NULL, 0, 1000, NULL); + mresult = curl_multi_poll(multi, NULL, 0, 1000, NULL); - if(mc) + if(mresult) break; } while(still_running); /* Always cleanup */ - curl_multi_remove_handle(mcurl, curl); - curl_multi_cleanup(mcurl); + curl_multi_remove_handle(multi, curl); + curl_multi_cleanup(multi); } curl_easy_cleanup(curl); } diff --git a/docs/examples/pop3-noop.c b/docs/examples/pop3-noop.c index 0ab6eb2d14c5..5e05713ec628 100644 --- a/docs/examples/pop3-noop.c +++ b/docs/examples/pop3-noop.c @@ -21,13 +21,12 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Perform a POP3 noop * */ - #include + #include /* This is a simple example showing how to perform a noop using libcurl's POP3 @@ -40,9 +39,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -60,12 +59,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_NOBODY, 1L); /* Perform the custom request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Always cleanup */ curl_easy_cleanup(curl); @@ -73,5 +72,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/pop3-retr.c b/docs/examples/pop3-retr.c index c89c77e5d649..af7e40293a33 100644 --- a/docs/examples/pop3-retr.c +++ b/docs/examples/pop3-retr.c @@ -21,13 +21,12 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Retrieve POP3 email * */ - #include + #include /* This is a simple example showing how to retrieve mail using libcurl's POP3 @@ -40,9 +39,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -54,12 +53,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_URL, "pop3://pop.example.com/1"); /* Perform the retr */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Always cleanup */ curl_easy_cleanup(curl); @@ -67,5 +66,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/pop3-ssl.c b/docs/examples/pop3-ssl.c index 63a9edca70d6..c38d41152a5a 100644 --- a/docs/examples/pop3-ssl.c +++ b/docs/examples/pop3-ssl.c @@ -21,13 +21,12 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Get POP3 email using implicit SSL * */ - #include + #include /* This is a simple example showing how to retrieve mail using libcurl's POP3 @@ -41,9 +40,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -67,7 +66,7 @@ int main(void) curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); #endif - /* If the site you are connecting to uses a different host name that what + /* If the site you are connecting to uses a different hostname than what * they have mentioned in their server certificate's commonName (or * subjectAltName) fields, libcurl refuses to connect. You can skip this * check, but it makes the connection insecure. */ @@ -81,12 +80,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); /* Perform the retr */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Always cleanup */ curl_easy_cleanup(curl); @@ -94,5 +93,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/pop3-stat.c b/docs/examples/pop3-stat.c index afaf79c9a4db..160f013d2d4d 100644 --- a/docs/examples/pop3-stat.c +++ b/docs/examples/pop3-stat.c @@ -21,13 +21,12 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Obtain POP3 message statistics * */ - #include + #include /* This is a simple example showing how to obtain message statistics using @@ -40,9 +39,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -60,12 +59,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_NOBODY, 1L); /* Perform the custom request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Always cleanup */ curl_easy_cleanup(curl); @@ -73,5 +72,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/pop3-tls.c b/docs/examples/pop3-tls.c index a4a7208986b4..4258088722bd 100644 --- a/docs/examples/pop3-tls.c +++ b/docs/examples/pop3-tls.c @@ -21,13 +21,12 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * POP3 using TLS * */ - #include + #include /* This is a simple example showing how to retrieve mail using libcurl's POP3 @@ -41,9 +40,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -81,12 +80,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); /* Perform the retr */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Always cleanup */ curl_easy_cleanup(curl); @@ -94,5 +93,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/pop3-top.c b/docs/examples/pop3-top.c index 7584503b0c2c..b96148768501 100644 --- a/docs/examples/pop3-top.c +++ b/docs/examples/pop3-top.c @@ -21,13 +21,12 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * POP3 example showing how to retrieve only the headers of an email * */ - #include + #include /* This is a simple example showing how to retrieve only the headers of a mail @@ -40,9 +39,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -57,12 +56,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "TOP 1 0"); /* Perform the custom request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Always cleanup */ curl_easy_cleanup(curl); @@ -70,5 +69,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/pop3-uidl.c b/docs/examples/pop3-uidl.c index aec10342311d..4cf571621a1e 100644 --- a/docs/examples/pop3-uidl.c +++ b/docs/examples/pop3-uidl.c @@ -21,13 +21,12 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * List the contents of a POP3 mailbox by unique ID * */ - #include + #include /* This is a simple example using libcurl's POP3 capabilities to list the @@ -40,9 +39,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -57,12 +56,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "UIDL"); /* Perform the custom request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Always cleanup */ curl_easy_cleanup(curl); @@ -70,5 +69,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/post-callback.c b/docs/examples/post-callback.c index 7c5a87e9acf7..729642cbce6a 100644 --- a/docs/examples/post-callback.c +++ b/docs/examples/post-callback.c @@ -27,11 +27,13 @@ */ #include #include + #include /* silly test data to POST */ -static const char data[]="Lorem ipsum dolor sit amet, consectetur adipiscing " - "elit. Sed vel urna neque. Ut quis leo metus. Quisque eleifend, ex at " +static const char data[] = + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. " + "Sed vel urna neque. Ut quis leo metus. Quisque eleifend, ex at " "laoreet rhoncus, odio ipsum semper metus, at tempus ante urna in mauris. " "Suspendisse ornare tempor venenatis. Ut dui neque, pellentesque a ______ " "eget, mattis vitae ligula. Fusce ut pharetra est. Ut ullamcorper mi ac " @@ -43,10 +45,10 @@ struct WriteThis { size_t sizeleft; }; -static size_t read_callback(char *dest, size_t size, size_t nmemb, void *userp) +static size_t read_cb(char *dest, size_t size, size_t nmemb, void *userp) { struct WriteThis *wt = (struct WriteThis *)userp; - size_t buffer_size = size*nmemb; + size_t buffer_size = size * nmemb; if(wt->sizeleft) { /* copy as much as possible from the source to the destination */ @@ -60,13 +62,13 @@ static size_t read_callback(char *dest, size_t size, size_t nmemb, void *userp) return copy_this_much; /* we copied this many bytes */ } - return 0; /* no more data left to deliver */ + return 0; /* no more data left to deliver */ } int main(void) { CURL *curl; - CURLcode res; + CURLcode result; struct WriteThis wt; @@ -74,12 +76,12 @@ int main(void) wt.sizeleft = strlen(data); /* In Windows, this inits the Winsock stuff */ - res = curl_global_init(CURL_GLOBAL_DEFAULT); + result = curl_global_init(CURL_GLOBAL_DEFAULT); /* Check for errors */ - if(res != CURLE_OK) { + if(result != CURLE_OK) { fprintf(stderr, "curl_global_init() failed: %s\n", - curl_easy_strerror(res)); - return (int)res; + curl_easy_strerror(result)); + return (int)result; } /* get a curl handle */ @@ -92,7 +94,7 @@ int main(void) curl_easy_setopt(curl, CURLOPT_POST, 1L); /* we want to use our own read function */ - curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback); + curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_cb); /* pointer to pass to our read function */ curl_easy_setopt(curl, CURLOPT_READDATA, &wt); @@ -112,7 +114,7 @@ int main(void) struct curl_slist *chunk = NULL; chunk = curl_slist_append(chunk, "Transfer-Encoding: chunked"); - res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk); + result = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk); /* use curl_slist_free_all() after the *perform() call to free this list again */ } @@ -135,18 +137,18 @@ int main(void) struct curl_slist *chunk = NULL; chunk = curl_slist_append(chunk, "Expect:"); - res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk); + result = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk); /* use curl_slist_free_all() after the *perform() call to free this list again */ } #endif - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); diff --git a/docs/examples/postinmemory.c b/docs/examples/postinmemory.c index 50b3b6fe7b27..f310c1448965 100644 --- a/docs/examples/postinmemory.c +++ b/docs/examples/postinmemory.c @@ -28,6 +28,7 @@ #include #include #include + #include struct MemoryStruct { @@ -35,8 +36,7 @@ struct MemoryStruct { size_t size; }; -static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, - void *userp) +static size_t write_cb(void *contents, size_t size, size_t nmemb, void *userp) { size_t realsize = size * nmemb; struct MemoryStruct *mem = (struct MemoryStruct *)userp; @@ -59,23 +59,23 @@ static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, int main(void) { CURL *curl; - CURLcode res; + CURLcode result; struct MemoryStruct chunk; static const char *postthis = "Field=1&Field=2&Field=3"; - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; chunk.memory = malloc(1); /* grown as needed by realloc above */ - chunk.size = 0; /* no data at this point */ + chunk.size = 0; /* no data at this point */ curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.org/"); /* send all data to this function */ - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); /* we pass our 'chunk' struct to the callback function */ curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); @@ -89,12 +89,12 @@ int main(void) /* if we do not provide POSTFIELDSIZE, libcurl calls strlen() by itself */ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(postthis)); - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) { + if(result != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); } else { /* @@ -103,7 +103,7 @@ int main(void) * * Do something nice with it! */ - printf("%s\n",chunk.memory); + printf("%s\n", chunk.memory); } /* always cleanup */ diff --git a/docs/examples/postit2-formadd.c b/docs/examples/postit2-formadd.c index 81f8bfd27c11..aee12ab0ac54 100644 --- a/docs/examples/postit2-formadd.c +++ b/docs/examples/postit2-formadd.c @@ -25,7 +25,6 @@ * HTTP Multipart formpost with file upload and two additional parts. * */ - /* * Example code that uploads a filename 'foo' to a remote script that accepts * "HTML form based" (as described in RFC 1738) uploads using HTTP POST. @@ -41,7 +40,6 @@ * * */ - #include #include @@ -50,16 +48,16 @@ int main(int argc, char *argv[]) { CURL *curl; - CURLcode res; + CURLcode result; struct curl_httppost *formpost = NULL; struct curl_httppost *lastptr = NULL; struct curl_slist *headerlist = NULL; static const char buf[] = "Expect:"; - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; CURL_IGNORE_DEPRECATION( /* Fill in the file upload field */ @@ -76,7 +74,6 @@ int main(int argc, char *argv[]) CURLFORM_COPYCONTENTS, "postit2-formadd.c", CURLFORM_END); - /* Fill in the submit field too, even if this is rarely needed */ curl_formadd(&formpost, &lastptr, @@ -99,12 +96,12 @@ int main(int argc, char *argv[]) curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); ) - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); diff --git a/docs/examples/postit2.c b/docs/examples/postit2.c index 57c7c86e3a2b..4535bed6e1ab 100644 --- a/docs/examples/postit2.c +++ b/docs/examples/postit2.c @@ -37,7 +37,6 @@ * * */ - #include #include @@ -47,9 +46,9 @@ int main(int argc, char *argv[]) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -86,12 +85,12 @@ int main(int argc, char *argv[]) curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist); curl_easy_setopt(curl, CURLOPT_MIMEPOST, form); - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); diff --git a/docs/examples/progressfunc.c b/docs/examples/progressfunc.c index 35adc6c82d56..22f876b5c83c 100644 --- a/docs/examples/progressfunc.c +++ b/docs/examples/progressfunc.c @@ -27,10 +27,11 @@ * */ #include + #include -#define MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL 3000000 -#define STOP_DOWNLOAD_AFTER_THIS_MANY_BYTES 6000 +#define MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL 3000000 +#define STOP_DOWNLOAD_AFTER_THIS_MANY_BYTES 6000 struct myprogress { curl_off_t lastruntime; /* type depends on version, see above */ @@ -53,14 +54,19 @@ static int xferinfo(void *p, be used */ if((curtime - myp->lastruntime) >= MINIMAL_PROGRESS_FUNCTIONALITY_INTERVAL) { myp->lastruntime = curtime; - fprintf(stderr, "TOTAL TIME: %lu.%06lu\r\n", - (unsigned long)(curtime / 1000000), - (unsigned long)(curtime % 1000000)); + fprintf(stderr, "TOTAL TIME: %" CURL_FORMAT_CURL_OFF_T + ".%06" CURL_FORMAT_CURL_OFF_T "\r\n", + curtime / 1000000, + curtime % 1000000); } - fprintf(stderr, "UP: %lu of %lu DOWN: %lu of %lu\r\n", - (unsigned long)ulnow, (unsigned long)ultotal, - (unsigned long)dlnow, (unsigned long)dltotal); + fprintf(stderr, + "UP: " + "%" CURL_FORMAT_CURL_OFF_T " of %" CURL_FORMAT_CURL_OFF_T " " + "DOWN: " + "%" CURL_FORMAT_CURL_OFF_T " of %" CURL_FORMAT_CURL_OFF_T "\r\n", + ulnow, ultotal, + dlnow, dltotal); if(dlnow > STOP_DOWNLOAD_AFTER_THIS_MANY_BYTES) return 1; @@ -71,9 +77,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -89,14 +95,14 @@ int main(void) curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &prog); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(res != CURLE_OK) - fprintf(stderr, "%s\n", curl_easy_strerror(res)); + if(result != CURLE_OK) + fprintf(stderr, "%s\n", curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/protofeats.c b/docs/examples/protofeats.c index fef4a3798d79..e8d8540089f9 100644 --- a/docs/examples/protofeats.c +++ b/docs/examples/protofeats.c @@ -26,20 +26,21 @@ * */ #include + #include -#if !CURL_AT_LEAST_VERSION(7,87,0) +#if !CURL_AT_LEAST_VERSION(7, 87, 0) #error "too old libcurl" #endif int main(void) { curl_version_info_data *ver; - const char *const *ptr; + const char * const *ptr; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; ver = curl_version_info(CURLVERSION_NOW); printf("Protocols:\n"); diff --git a/docs/examples/range.c b/docs/examples/range.c index ec85ed878dc3..9555725dabf5 100644 --- a/docs/examples/range.c +++ b/docs/examples/range.c @@ -31,20 +31,20 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/resolve.c b/docs/examples/resolve.c index 4ccc3ff1d815..e56c8efb8743 100644 --- a/docs/examples/resolve.c +++ b/docs/examples/resolve.c @@ -27,6 +27,7 @@ * */ #include + #include int main(void) @@ -41,15 +42,15 @@ int main(void) struct curl_slist *host = curl_slist_append(NULL, "example.com:443:127.0.0.1"); - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_RESOLVE, host); curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* always cleanup */ curl_easy_cleanup(curl); @@ -58,5 +59,5 @@ int main(void) curl_slist_free_all(host); curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/rtsp-options.c b/docs/examples/rtsp-options.c index 50d5e2f27ee0..7c7ff945f962 100644 --- a/docs/examples/rtsp-options.c +++ b/docs/examples/rtsp-options.c @@ -22,19 +22,20 @@ * ***************************************************************************/ /* - * Very simple RTSP request sending OPTIONS. + * Simple RTSP request sending OPTIONS. * */ #include + #include int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -44,12 +45,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_RTSP_REQUEST, CURL_RTSPREQ_OPTIONS); - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); diff --git a/docs/examples/sendrecv.c b/docs/examples/sendrecv.c index 71faeb4ad31e..21a09b65841e 100644 --- a/docs/examples/sendrecv.c +++ b/docs/examples/sendrecv.c @@ -25,9 +25,9 @@ * Demonstrate curl_easy_send() and curl_easy_recv() usage. * */ - #include #include + #include /* Avoid warning in FD_SET() with pre-2020 Cygwin/MSYS releases: @@ -83,9 +83,9 @@ int main(void) const char *request = "GET / HTTP/1.0\r\nHost: example.com\r\n\r\n"; size_t request_len = strlen(request); - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; /* A general note of caution here: if you are using curl_easy_recv() or curl_easy_send() to implement HTTP or _any_ other protocol libcurl @@ -103,18 +103,18 @@ int main(void) 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); + result = curl_easy_perform(curl); - if(res != CURLE_OK) { - printf("Error: %s\n", curl_easy_strerror(res)); + if(result != CURLE_OK) { + printf("Error: %s\n", curl_easy_strerror(result)); return 1; } /* Extract the socket from the curl handle - we need it for waiting. */ - res = curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sockfd); + result = curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sockfd); - if(res != CURLE_OK) { - printf("Error: %s\n", curl_easy_strerror(res)); + if(result != CURLE_OK) { + printf("Error: %s\n", curl_easy_strerror(result)); return 1; } @@ -127,18 +127,18 @@ int main(void) size_t nsent; do { nsent = 0; - res = curl_easy_send(curl, request + nsent_total, - request_len - nsent_total, &nsent); + result = curl_easy_send(curl, request + nsent_total, + request_len - nsent_total, &nsent); nsent_total += nsent; - if(res == CURLE_AGAIN && !wait_on_socket(sockfd, 0, 60000L)) { + if(result == CURLE_AGAIN && !wait_on_socket(sockfd, 0, 60000L)) { printf("Error: timeout.\n"); return 1; } - } while(res == CURLE_AGAIN); + } while(result == CURLE_AGAIN); - if(res != CURLE_OK) { - printf("Error: %s\n", curl_easy_strerror(res)); + if(result != CURLE_OK) { + printf("Error: %s\n", curl_easy_strerror(result)); return 1; } @@ -154,16 +154,16 @@ int main(void) size_t nread; do { nread = 0; - res = curl_easy_recv(curl, buf, sizeof(buf), &nread); + result = curl_easy_recv(curl, buf, sizeof(buf), &nread); - if(res == CURLE_AGAIN && !wait_on_socket(sockfd, 1, 60000L)) { + if(result == CURLE_AGAIN && !wait_on_socket(sockfd, 1, 60000L)) { printf("Error: timeout.\n"); return 1; } - } while(res == CURLE_AGAIN); + } while(result == CURLE_AGAIN); - if(res != CURLE_OK) { - printf("Error: %s\n", curl_easy_strerror(res)); + if(result != CURLE_OK) { + printf("Error: %s\n", curl_easy_strerror(result)); break; } diff --git a/docs/examples/sepheaders.c b/docs/examples/sepheaders.c index cea07fd56698..134ecb94a4c6 100644 --- a/docs/examples/sepheaders.c +++ b/docs/examples/sepheaders.c @@ -25,12 +25,18 @@ * Simple HTTP GET that stores the headers in a separate file * */ +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* for fopen() */ +#endif +#endif + #include #include #include -static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream) +static size_t write_cb(void *ptr, size_t size, size_t nmemb, void *stream) { size_t written = fwrite(ptr, size, nmemb, (FILE *)stream); return written; @@ -38,33 +44,33 @@ static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream) int main(void) { - CURL *curl_handle; + CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; /* init the curl session */ - curl_handle = curl_easy_init(); - if(curl_handle) { + curl = curl_easy_init(); + if(curl) { static const char *headerfilename = "head.out"; FILE *headerfile; static const char *bodyfilename = "body.out"; FILE *bodyfile; /* set URL to get */ - curl_easy_setopt(curl_handle, CURLOPT_URL, "https://example.com"); + curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); /* no progress meter please */ - curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1L); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L); /* send all data to this function */ - curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); /* open the header file */ headerfile = fopen(headerfilename, "wb"); if(!headerfile) { - curl_easy_cleanup(curl_handle); + curl_easy_cleanup(curl); curl_global_cleanup(); return -1; } @@ -72,20 +78,20 @@ int main(void) /* open the body file */ bodyfile = fopen(bodyfilename, "wb"); if(!bodyfile) { - curl_easy_cleanup(curl_handle); + curl_easy_cleanup(curl); fclose(headerfile); curl_global_cleanup(); return -1; } /* we want the headers be written to this file handle */ - curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, headerfile); + curl_easy_setopt(curl, CURLOPT_HEADERDATA, headerfile); /* we want the body be written to this file handle instead of stdout */ - curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, bodyfile); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, bodyfile); /* get it! */ - res = curl_easy_perform(curl_handle); + result = curl_easy_perform(curl); /* close the header file */ fclose(headerfile); @@ -94,10 +100,10 @@ int main(void) fclose(bodyfile); /* cleanup curl stuff */ - curl_easy_cleanup(curl_handle); + curl_easy_cleanup(curl); } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/sessioninfo.c b/docs/examples/sessioninfo.c index c7ea52ccc2e8..788ccf575b96 100644 --- a/docs/examples/sessioninfo.c +++ b/docs/examples/sessioninfo.c @@ -43,17 +43,17 @@ static CURL *curl; -static size_t wrfu(void *ptr, size_t size, size_t nmemb, void *stream) +static size_t write_cb(void *ptr, size_t size, size_t nmemb, void *stream) { const struct curl_tlssessioninfo *info; - CURLcode res; + CURLcode result; (void)stream; (void)ptr; - res = curl_easy_getinfo(curl, CURLINFO_TLS_SESSION, &info); + result = curl_easy_getinfo(curl, CURLINFO_TLS_SESSION, &info); - if(!res) { + if(!result) { unsigned int cert_list_size; const gnutls_datum_t *chainp; @@ -73,8 +73,8 @@ static size_t wrfu(void *ptr, size_t size, size_t nmemb, void *stream) gnutls_x509_crt_import(cert, &chainp[i], GNUTLS_X509_FMT_DER)) { if(GNUTLS_E_SUCCESS == gnutls_x509_crt_print(cert, GNUTLS_CRT_PRINT_FULL, &dn)) { - fprintf(stderr, "Certificate #%u: %.*s", i, - (int)dn.size, dn.data); + fprintf(stderr, "Certificate #%u: %.*s", i, (int)dn.size, + dn.data); gnutls_free(dn.data); } @@ -96,22 +96,22 @@ static size_t wrfu(void *ptr, size_t size, size_t nmemb, void *stream) int main(void) { - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/"); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, wrfu); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/sftpget.c b/docs/examples/sftpget.c index 36653c5b828c..f1484eb80c97 100644 --- a/docs/examples/sftpget.c +++ b/docs/examples/sftpget.c @@ -25,6 +25,11 @@ * Gets a file using an SFTP URL. * */ +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* for fopen() */ +#endif +#endif #include @@ -45,8 +50,7 @@ struct FtpFile { FILE *stream; }; -static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, - void *stream) +static size_t write_cb(void *buffer, size_t size, size_t nmemb, void *stream) { struct FtpFile *out = (struct FtpFile *)stream; if(!out->stream) { @@ -58,7 +62,6 @@ static size_t my_fwrite(void *buffer, size_t size, size_t nmemb, return fwrite(buffer, size, nmemb, out->stream); } - int main(void) { CURL *curl; @@ -67,9 +70,9 @@ int main(void) NULL }; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -79,7 +82,7 @@ int main(void) curl_easy_setopt(curl, CURLOPT_URL, "sftp://user@server/home/user/file.txt"); /* Define our callback to get called when there is data to be written */ - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); /* Set a pointer to our struct to pass to the callback */ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile); @@ -93,14 +96,14 @@ int main(void) /* Switch on full protocol/debug output */ curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* always cleanup */ curl_easy_cleanup(curl); - if(CURLE_OK != res) { + if(CURLE_OK != result) { /* we failed */ - fprintf(stderr, "curl told us %d\n", res); + fprintf(stderr, "curl told us %d\n", result); } } @@ -109,5 +112,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/sftpuploadresume.c b/docs/examples/sftpuploadresume.c index 8745abe78b8f..02f18897a31c 100644 --- a/docs/examples/sftpuploadresume.c +++ b/docs/examples/sftpuploadresume.c @@ -25,13 +25,19 @@ * Upload to SFTP, resuming a previously aborted transfer. * */ +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* for fopen() */ +#endif +#endif #include #include + #include /* read data to upload */ -static size_t readfunc(char *ptr, size_t size, size_t nmemb, void *stream) +static size_t read_cb(char *ptr, size_t size, size_t nmemb, void *stream) { FILE *f = (FILE *)stream; size_t n; @@ -49,34 +55,35 @@ static size_t readfunc(char *ptr, size_t size, size_t nmemb, void *stream) */ static curl_off_t sftpGetRemoteFileSize(const char *i_remoteFile) { - CURLcode result = CURLE_GOT_NOTHING; curl_off_t remoteFileSizeByte = -1; - CURL *curlHandlePtr = curl_easy_init(); - - curl_easy_setopt(curlHandlePtr, CURLOPT_VERBOSE, 1L); - - curl_easy_setopt(curlHandlePtr, CURLOPT_URL, i_remoteFile); - curl_easy_setopt(curlHandlePtr, CURLOPT_NOPROGRESS, 1L); - curl_easy_setopt(curlHandlePtr, CURLOPT_NOBODY, 1L); - curl_easy_setopt(curlHandlePtr, CURLOPT_HEADER, 1L); - curl_easy_setopt(curlHandlePtr, CURLOPT_FILETIME, 1L); - - result = curl_easy_perform(curlHandlePtr); - if(CURLE_OK == result) { - result = curl_easy_getinfo(curlHandlePtr, - CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, - &remoteFileSizeByte); - if(result) - return -1; - printf("filesize: %lu\n", (unsigned long)remoteFileSizeByte); + CURL *curl = curl_easy_init(); + + if(curl) { + CURLcode result; + + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); + + curl_easy_setopt(curl, CURLOPT_URL, i_remoteFile); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L); + curl_easy_setopt(curl, CURLOPT_NOBODY, 1L); + curl_easy_setopt(curl, CURLOPT_HEADER, 1L); + curl_easy_setopt(curl, CURLOPT_FILETIME, 1L); + + result = curl_easy_perform(curl); + if(CURLE_OK == result) { + result = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, + &remoteFileSizeByte); + if(result) + return -1; + printf("filesize: %" CURL_FORMAT_CURL_OFF_T "\n", remoteFileSizeByte); + } + curl_easy_cleanup(curl); } - curl_easy_cleanup(curlHandlePtr); return remoteFileSizeByte; } - -static int sftpResumeUpload(CURL *curlhandle, const char *remotepath, +static int sftpResumeUpload(CURL *curl, const char *remotepath, const char *localpath) { FILE *f = NULL; @@ -90,24 +97,22 @@ static int sftpResumeUpload(CURL *curlhandle, const char *remotepath, f = fopen(localpath, "rb"); if(!f) { -#ifndef UNDER_CE perror(NULL); -#endif return 0; } - curl_easy_setopt(curlhandle, CURLOPT_UPLOAD, 1L); - curl_easy_setopt(curlhandle, CURLOPT_URL, remotepath); - curl_easy_setopt(curlhandle, CURLOPT_READFUNCTION, readfunc); - curl_easy_setopt(curlhandle, CURLOPT_READDATA, f); + curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); + curl_easy_setopt(curl, CURLOPT_URL, remotepath); + curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_cb); + curl_easy_setopt(curl, CURLOPT_READDATA, f); -#if defined(_WIN32) && !defined(UNDER_CE) +#ifdef _WIN32 _fseeki64(f, remoteFileSizeByte, SEEK_SET); #else fseek(f, (long)remoteFileSizeByte, SEEK_SET); #endif - curl_easy_setopt(curlhandle, CURLOPT_APPEND, 1L); - result = curl_easy_perform(curlhandle); + curl_easy_setopt(curl, CURLOPT_APPEND, 1L); + result = curl_easy_perform(curl); fclose(f); @@ -121,22 +126,22 @@ static int sftpResumeUpload(CURL *curlhandle, const char *remotepath, int main(void) { - CURL *curlhandle = NULL; + CURL *curl = NULL; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; - curlhandle = curl_easy_init(); - if(curlhandle) { + curl = curl_easy_init(); + if(curl) { const char *remote = "sftp://user:pass@example.com/path/filename"; const char *filename = "filename"; - if(!sftpResumeUpload(curlhandle, remote, filename)) { + if(!sftpResumeUpload(curl, remote, filename)) { printf("resumed upload using curl %s failed\n", curl_version()); } - curl_easy_cleanup(curlhandle); + curl_easy_cleanup(curl); } curl_global_cleanup(); diff --git a/docs/examples/shared-connection-cache.c b/docs/examples/shared-connection-cache.c index a8549d776668..475bb182a8cb 100644 --- a/docs/examples/shared-connection-cache.c +++ b/docs/examples/shared-connection-cache.c @@ -26,21 +26,22 @@ * */ #include + #include -static void my_lock(CURL *handle, curl_lock_data data, - curl_lock_access laccess, void *useptr) +static void my_lock(CURL *curl, curl_lock_data data, curl_lock_access laccess, + void *useptr) { - (void)handle; + (void)curl; (void)data; (void)laccess; (void)useptr; fprintf(stderr, "-> Mutex lock\n"); } -static void my_unlock(CURL *handle, curl_lock_data data, void *useptr) +static void my_unlock(CURL *curl, curl_lock_data data, void *useptr) { - (void)handle; + (void)curl; (void)data; (void)useptr; fprintf(stderr, "<- Mutex unlock\n"); @@ -51,9 +52,9 @@ int main(void) CURLSH *share; int i; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; share = curl_share_init(); curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT); @@ -72,12 +73,12 @@ int main(void) /* use the share object */ curl_easy_setopt(curl, CURLOPT_SHARE, share); - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); @@ -86,5 +87,5 @@ int main(void) curl_share_cleanup(share); curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/simple.c b/docs/examples/simple.c index 29ed14313eda..6f0751775f80 100644 --- a/docs/examples/simple.c +++ b/docs/examples/simple.c @@ -22,19 +22,20 @@ * ***************************************************************************/ /* - * Very simple HTTP GET + * Simple HTTP GET * */ #include + #include int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -42,12 +43,12 @@ int main(void) /* example.com is redirected, so we tell libcurl to follow redirection */ curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); diff --git a/docs/examples/simplepost.c b/docs/examples/simplepost.c index b1175ba924a4..7b9356acf9ea 100644 --- a/docs/examples/simplepost.c +++ b/docs/examples/simplepost.c @@ -22,11 +22,12 @@ * ***************************************************************************/ /* - * Very simple HTTP POST + * Simple HTTP POST * */ #include #include + #include int main(void) @@ -35,9 +36,9 @@ int main(void) CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -47,16 +48,16 @@ int main(void) /* if we do not provide POSTFIELDSIZE, libcurl calls strlen() by itself */ curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(postthis)); - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/simplessl.c b/docs/examples/simplessl.c index 5da79a79a068..9885dfd91de2 100644 --- a/docs/examples/simplessl.c +++ b/docs/examples/simplessl.c @@ -25,6 +25,12 @@ * Shows HTTPS usage with client certs and optional ssl engine use. * */ +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* for fopen() */ +#endif +#endif + #include #include @@ -40,17 +46,12 @@ 4. if you do not use a crypto engine: 4.1. set pKeyName to the filename of your client key 4.2. if the format of the key file is DER, set pKeyType to "DER" - - !! verify of the server certificate is not implemented here !! - - **** This example only works with libcurl 7.9.3 and later! **** - */ int main(void) { - CURL *curl; - CURLcode res; + CURL *curl = NULL; + CURLcode result; FILE *headerfile; const char *pPassphrase = NULL; @@ -61,98 +62,89 @@ int main(void) const char *pKeyName; const char *pKeyType; - const char *pEngine; - #ifdef USE_ENGINE - pKeyName = "rsa_test"; - pKeyType = "ENG"; - pEngine = "chil"; /* for nCipher HSM... */ + pKeyName = "rsa_test"; + pKeyType = "ENG"; #else - pKeyName = "testkey.pem"; - pKeyType = "PEM"; - pEngine = NULL; + pKeyName = "testkey.pem"; + pKeyType = "PEM"; #endif + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) { + return (int)result; + } + headerfile = fopen(pHeaderFile, "wb"); if(!headerfile) - return 1; - - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) { - fclose(headerfile); - return (int)res; - } + goto error; curl = curl_easy_init(); - if(curl) { - /* what call to write: */ - curl_easy_setopt(curl, CURLOPT_URL, "HTTPS://secure.site.example"); - curl_easy_setopt(curl, CURLOPT_HEADERDATA, headerfile); + if(!curl) + goto error; -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4127) /* conditional expression is constant */ -#endif - do { /* dummy loop, just to break out from */ - if(pEngine) { - /* use crypto engine */ - if(curl_easy_setopt(curl, CURLOPT_SSLENGINE, pEngine) != CURLE_OK) { - /* load the crypto engine */ - fprintf(stderr, "cannot set crypto engine\n"); - break; - } - if(curl_easy_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1L) != CURLE_OK) { - /* set the crypto engine as default */ - /* only needed for the first time you load - an engine in a curl object... */ - fprintf(stderr, "cannot set crypto engine as default\n"); - break; - } - } - /* cert is stored PEM coded in file... */ - /* since PEM is default, we needn't set it for PEM */ - curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM"); - - /* set the cert for client authentication */ - curl_easy_setopt(curl, CURLOPT_SSLCERT, pCertFile); - - /* sorry, for engine we must set the passphrase - (if the key has one...) */ - if(pPassphrase) - curl_easy_setopt(curl, CURLOPT_KEYPASSWD, pPassphrase); - - /* if we use a key stored in a crypto engine, - we must set the key type to "ENG" */ - curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, pKeyType); - - /* set the private key (file or ID in engine) */ - curl_easy_setopt(curl, CURLOPT_SSLKEY, pKeyName); - - /* set the file with the certs validating the server */ - curl_easy_setopt(curl, CURLOPT_CAINFO, pCACertFile); - - /* disconnect if we cannot validate server's cert */ - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); - - /* Perform the request, res gets 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)); - - /* we are done... */ - } while(0); -#ifdef _MSC_VER -#pragma warning(pop) + /* what call to write: */ + curl_easy_setopt(curl, CURLOPT_URL, "https://secure.site.example/"); + curl_easy_setopt(curl, CURLOPT_HEADERDATA, headerfile); + +#ifdef USE_ENGINE + /* use crypto engine. nCipher HSM... */ + if(curl_easy_setopt(curl, CURLOPT_SSLENGINE, "chil") != CURLE_OK) { + /* load the crypto engine */ + fprintf(stderr, "cannot set crypto engine\n"); + goto error; + } + if(curl_easy_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1L) != CURLE_OK) { + /* set the crypto engine as default */ + /* only needed for the first time you load + an engine in a curl object... */ + fprintf(stderr, "cannot set crypto engine as default\n"); + goto error; + } #endif - /* always cleanup */ + + /* cert is stored PEM coded in file... */ + /* since PEM is default, we need not set it for PEM */ + curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM"); + + /* set the cert for client authentication */ + curl_easy_setopt(curl, CURLOPT_SSLCERT, pCertFile); + + /* sorry, for engine we must set the passphrase + (if the key has one...) */ + if(pPassphrase) + curl_easy_setopt(curl, CURLOPT_KEYPASSWD, pPassphrase); + + /* if we use a key stored in a crypto engine, + we must set the key type to "ENG" */ + curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, pKeyType); + + /* set the private key (file or ID in engine) */ + curl_easy_setopt(curl, CURLOPT_SSLKEY, pKeyName); + + /* set the file with the certs validating the server */ + curl_easy_setopt(curl, CURLOPT_CAINFO, pCACertFile); + + /* disconnect if we cannot validate server's cert */ + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); + + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); + /* Check for errors */ + if(result != CURLE_OK) + fprintf(stderr, "curl_easy_perform() failed: %s\n", + curl_easy_strerror(result)); + +error: + + /* always cleanup */ + if(curl) curl_easy_cleanup(curl); - } - curl_global_cleanup(); + if(headerfile) + fclose(headerfile); - fclose(headerfile); + curl_global_cleanup(); - return 0; + return (int)result; } diff --git a/docs/examples/smooth-gtk-thread.c b/docs/examples/smooth-gtk-thread.c index 5a0bb2d05e97..1c9951dfceeb 100644 --- a/docs/examples/smooth-gtk-thread.c +++ b/docs/examples/smooth-gtk-thread.c @@ -22,8 +22,8 @@ * ***************************************************************************/ /* - * A multi threaded application that uses a progress bar to show - * status. It uses Gtk+ to make a smooth pulse. + * A multi-threaded application that uses a progress bar to show + * status. It uses Gtk+ to make a smooth pulse. * */ /* @@ -45,10 +45,10 @@ #define NUMT 4 -pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; -int j = 0; -gint num_urls = 9; /* Just make sure this is less than urls[]*/ -const char * const urls[]= { +static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; +static int j = 0; +static gint num_urls = 9; /* Just make sure this is less than urls[] */ +static const char * const urls[] = { "90022", "90023", "90024", @@ -60,7 +60,7 @@ const char * const urls[]= { "90030" }; -size_t write_file(void *ptr, size_t size, size_t nmemb, FILE *stream) +static size_t write_cb(void *ptr, size_t size, size_t nmemb, FILE *stream) { return fwrite(ptr, size, nmemb, stream); } @@ -80,7 +80,7 @@ static void run_one(gchar *http, int j) /* Write to the file */ curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_file); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); (void)curl_easy_perform(curl); fclose(outfile); @@ -89,7 +89,7 @@ static void run_one(gchar *http, int j) } } -void *pull_one_url(void *NaN) +static void *pull_one_url(void *NaN) { /* protect the reading and increasing of 'j' with a mutex */ pthread_mutex_lock(&lock); @@ -108,11 +108,10 @@ void *pull_one_url(void *NaN) return NULL; } - -gboolean pulse_bar(gpointer data) +static gboolean pulse_bar(gpointer data) { gdk_threads_enter(); - gtk_progress_bar_pulse(GTK_PROGRESS_BAR (data)); + gtk_progress_bar_pulse(GTK_PROGRESS_BAR(data)); gdk_threads_leave(); /* Return true so the function is called again; returning false removes this @@ -121,19 +120,19 @@ gboolean pulse_bar(gpointer data) return TRUE; } -void *create_thread(void *progress_bar) +static void *create_thread(void *progress_bar) { pthread_t tid[NUMT]; int i; /* Make sure I do not create more threads than urls. */ - for(i = 0; i < NUMT && i < num_urls ; i++) { + for(i = 0; i < NUMT && i < num_urls; i++) { int error = pthread_create(&tid[i], NULL, /* default attributes please */ pull_one_url, NULL); if(error) - fprintf(stderr, "Couldn't run thread number %d, errno %d\n", i, error); + fprintf(stderr, "Could not run thread number %d, errno %d\n", i, error); else fprintf(stderr, "Thread %d, gets %s\n", i, urls[i]); } @@ -155,9 +154,7 @@ void *create_thread(void *progress_bar) /* [Un]Comment this out to kill the program rather than pushing close. */ /* gtk_main_quit(); */ - return NULL; - } static gboolean cb_delete(GtkWidget *window, gpointer data) @@ -171,9 +168,9 @@ int main(int argc, char **argv) GtkWidget *top_window, *outside_frame, *inside_frame, *progress_bar; /* Must initialize libcurl before any threads are started */ - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; /* Init thread */ g_thread_init(NULL); @@ -198,7 +195,7 @@ int main(int argc, char **argv) /* Progress bar */ progress_bar = gtk_progress_bar_new(); - gtk_progress_bar_pulse(GTK_PROGRESS_BAR (progress_bar)); + gtk_progress_bar_pulse(GTK_PROGRESS_BAR(progress_bar)); /* Make uniform pulsing */ gint pulse_ref = g_timeout_add(300, pulse_bar, progress_bar); g_object_set_data(G_OBJECT(progress_bar), "pulse_id", @@ -208,7 +205,7 @@ int main(int argc, char **argv) gtk_widget_show_all(top_window); printf("gtk_widget_show_all\n"); - g_signal_connect(G_OBJECT (top_window), "delete-event", + g_signal_connect(G_OBJECT(top_window), "delete-event", G_CALLBACK(cb_delete), NULL); if(!g_thread_create(&create_thread, progress_bar, FALSE, NULL) != 0) diff --git a/docs/examples/smtp-authzid.c b/docs/examples/smtp-authzid.c index 758a7fdaaf2a..64540cb033e9 100644 --- a/docs/examples/smtp-authzid.c +++ b/docs/examples/smtp-authzid.c @@ -21,14 +21,13 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Send email on behalf of another user with SMTP * */ - #include #include + #include /* @@ -41,13 +40,13 @@ /* The libcurl options want plain addresses, the viewable headers in the mail * can get a full name as well. */ -#define FROM_ADDR "" -#define SENDER_ADDR "" -#define TO_ADDR "" +#define FROM_ADDR "" +#define SENDER_ADDR "" +#define TO_ADDR "" -#define FROM_MAIL "Ursel " FROM_ADDR -#define SENDER_MAIL "Kurt " SENDER_ADDR -#define TO_MAIL "A Receiver " TO_ADDR +#define FROM_MAIL "Ursel " FROM_ADDR +#define SENDER_MAIL "Kurt " SENDER_ADDR +#define TO_MAIL "A Receiver " TO_ADDR static const char *payload_text = "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n" @@ -67,38 +66,35 @@ struct upload_status { size_t bytes_read; }; -static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp) +static size_t read_cb(char *ptr, size_t size, size_t nmemb, void *userp) { struct upload_status *upload_ctx = (struct upload_status *)userp; const char *data; size_t room = size * nmemb; + size_t len; - if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) { + if((size == 0) || (nmemb == 0) || ((size * nmemb) < 1)) { return 0; } data = &payload_text[upload_ctx->bytes_read]; - if(data) { - size_t len = strlen(data); - if(room < len) - len = room; - memcpy(ptr, data, len); - upload_ctx->bytes_read += len; - - return len; - } + len = strlen(data); + if(room < len) + len = room; + memcpy(ptr, data, len); + upload_ctx->bytes_read += len; - return 0; + return len; } int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -136,17 +132,17 @@ int main(void) /* We are using a callback function to specify the payload (the headers and * body of the message). You could just use the CURLOPT_READDATA option to * specify a FILE pointer to read from. */ - curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source); + curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_cb); curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx); curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); /* Send the message */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Free the list of recipients */ curl_slist_free_all(recipients); @@ -164,5 +160,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/smtp-expn.c b/docs/examples/smtp-expn.c index 727880d6199e..9b201240dcdc 100644 --- a/docs/examples/smtp-expn.c +++ b/docs/examples/smtp-expn.c @@ -21,14 +21,13 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Expand an SMTP email mailing list * */ - #include #include + #include /* This is a simple example showing how to expand an email mailing list. @@ -43,9 +42,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -62,12 +61,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "EXPN"); /* Perform the custom request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Free the list of recipients */ curl_slist_free_all(recipients); diff --git a/docs/examples/smtp-mail.c b/docs/examples/smtp-mail.c index d3f4346b8c0a..0a3e73d39f9d 100644 --- a/docs/examples/smtp-mail.c +++ b/docs/examples/smtp-mail.c @@ -21,14 +21,13 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Send email with SMTP * */ - #include #include + #include /* @@ -38,9 +37,9 @@ /* The libcurl options want plain addresses, the viewable headers in the mail * can get a full name as well. */ -#define FROM_ADDR "" -#define TO_ADDR "" -#define CC_ADDR "" +#define FROM_ADDR "" +#define TO_ADDR "" +#define CC_ADDR "" #define FROM_MAIL "Sender Person " FROM_ADDR #define TO_MAIL "A Receiver " TO_ADDR @@ -64,38 +63,35 @@ struct upload_status { size_t bytes_read; }; -static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp) +static size_t read_cb(char *ptr, size_t size, size_t nmemb, void *userp) { struct upload_status *upload_ctx = (struct upload_status *)userp; const char *data; size_t room = size * nmemb; + size_t len; - if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) { + if((size == 0) || (nmemb == 0) || ((size * nmemb) < 1)) { return 0; } data = &payload_text[upload_ctx->bytes_read]; - if(data) { - size_t len = strlen(data); - if(room < len) - len = room; - memcpy(ptr, data, len); - upload_ctx->bytes_read += len; - - return len; - } + len = strlen(data); + if(room < len) + len = room; + memcpy(ptr, data, len); + upload_ctx->bytes_read += len; - return 0; + return len; } int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -124,17 +120,17 @@ int main(void) /* We are using a callback function to specify the payload (the headers and * body of the message). You could just use the CURLOPT_READDATA option to * specify a FILE pointer to read from. */ - curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source); + curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_cb); curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx); curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); /* Send the message */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Free the list of recipients */ curl_slist_free_all(recipients); @@ -152,5 +148,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/smtp-mime.c b/docs/examples/smtp-mime.c index d26021ef3407..7aa610789a04 100644 --- a/docs/examples/smtp-mime.c +++ b/docs/examples/smtp-mime.c @@ -21,14 +21,13 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Send SMTP mime emails * */ - #include #include + #include /* This is a simple example showing how to send mime mail using libcurl's SMTP @@ -38,9 +37,9 @@ * Note that this example requires libcurl 7.56.0 or above. */ -#define FROM "" -#define TO "" -#define CC "" +#define FROM "" +#define TO "" +#define CC "" static const char *headers_text[] = { "Date: Tue, 22 Aug 2017 14:08:43 +0100", @@ -48,7 +47,7 @@ static const char *headers_text[] = { "From: " FROM " (Example User)", "Cc: " CC " (Another example User)", "Message-ID: ", + "rfcpedant.example.org>", "Subject: example sending a MIME-formatted message", NULL }; @@ -67,14 +66,13 @@ static const char inline_html[] = "email viewers able to handle HTML.

" "\r\n"; - int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -142,12 +140,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime); /* Send the message */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Free lists. */ curl_slist_free_all(recipients); @@ -169,5 +167,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/smtp-multi.c b/docs/examples/smtp-multi.c index f7619465ee17..0ce691115225 100644 --- a/docs/examples/smtp-multi.c +++ b/docs/examples/smtp-multi.c @@ -21,13 +21,12 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Send SMTP email with the multi interface * */ - #include + #include /* This is an example showing how to send mail using libcurl's SMTP @@ -35,9 +34,9 @@ * libcurl's multi interface. */ -#define FROM_MAIL "" -#define TO_MAIL "" -#define CC_MAIL "" +#define FROM_MAIL "" +#define TO_MAIL "" +#define CC_MAIL "" static const char *payload_text = "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n" @@ -57,45 +56,42 @@ struct upload_status { size_t bytes_read; }; -static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp) +static size_t read_cb(char *ptr, size_t size, size_t nmemb, void *userp) { struct upload_status *upload_ctx = (struct upload_status *)userp; const char *data; size_t room = size * nmemb; + size_t len; - if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) { + if((size == 0) || (nmemb == 0) || ((size * nmemb) < 1)) { return 0; } data = &payload_text[upload_ctx->bytes_read]; - if(data) { - size_t len = strlen(data); - if(room < len) - len = room; - memcpy(ptr, data, len); - upload_ctx->bytes_read += len; + len = strlen(data); + if(room < len) + len = room; + memcpy(ptr, data, len); + upload_ctx->bytes_read += len; - return len; - } - - return 0; + return len; } int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { - CURLM *mcurl; + CURLM *multi; - mcurl = curl_multi_init(); - if(mcurl) { + multi = curl_multi_init(); + if(multi) { int still_running = 1; struct curl_slist *recipients = NULL; struct upload_status upload_ctx = { 0 }; @@ -122,21 +118,21 @@ int main(void) /* We are using a callback function to specify the payload (the headers * and body of the message). You could just use the CURLOPT_READDATA * option to specify a FILE pointer to read from. */ - curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source); + curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_cb); curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx); curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); /* Tell the multi stack about our easy handle */ - curl_multi_add_handle(mcurl, curl); + curl_multi_add_handle(multi, curl); do { - CURLMcode mc = curl_multi_perform(mcurl, &still_running); + CURLMcode mresult = curl_multi_perform(multi, &still_running); if(still_running) /* wait for activity, timeout or "nothing" */ - mc = curl_multi_poll(mcurl, NULL, 0, 1000, NULL); + mresult = curl_multi_poll(multi, NULL, 0, 1000, NULL); - if(mc) + if(mresult) break; } while(still_running); @@ -145,8 +141,8 @@ int main(void) curl_slist_free_all(recipients); /* Always cleanup */ - curl_multi_remove_handle(mcurl, curl); - curl_multi_cleanup(mcurl); + curl_multi_remove_handle(multi, curl); + curl_multi_cleanup(multi); } curl_easy_cleanup(curl); } diff --git a/docs/examples/smtp-ssl.c b/docs/examples/smtp-ssl.c index ca73b73fca9a..acc559562f81 100644 --- a/docs/examples/smtp-ssl.c +++ b/docs/examples/smtp-ssl.c @@ -21,14 +21,13 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Send SMTP email using implicit SSL * */ - #include #include + #include /* This is a simple example showing how to send mail using libcurl's SMTP @@ -39,9 +38,9 @@ * Note that this example requires libcurl 7.20.0 or above. */ -#define FROM_MAIL "" -#define TO_MAIL "" -#define CC_MAIL "" +#define FROM_MAIL "" +#define TO_MAIL "" +#define CC_MAIL "" static const char *payload_text = "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n" @@ -61,38 +60,35 @@ struct upload_status { size_t bytes_read; }; -static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp) +static size_t read_cb(char *ptr, size_t size, size_t nmemb, void *userp) { struct upload_status *upload_ctx = (struct upload_status *)userp; const char *data; size_t room = size * nmemb; + size_t len; - if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) { + if((size == 0) || (nmemb == 0) || ((size * nmemb) < 1)) { return 0; } data = &payload_text[upload_ctx->bytes_read]; - if(data) { - size_t len = strlen(data); - if(room < len) - len = room; - memcpy(ptr, data, len); - upload_ctx->bytes_read += len; - - return len; - } + len = strlen(data); + if(room < len) + len = room; + memcpy(ptr, data, len); + upload_ctx->bytes_read += len; - return 0; + return len; } int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -119,7 +115,7 @@ int main(void) curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); #endif - /* If the site you are connecting to uses a different host name that what + /* If the site you are connecting to uses a different hostname than what * they have mentioned in their server certificate's commonName (or * subjectAltName) fields, libcurl refuses to connect. You can skip this * check, but it makes the connection insecure. */ @@ -146,7 +142,7 @@ int main(void) /* We are using a callback function to specify the payload (the headers and * body of the message). You could just use the CURLOPT_READDATA option to * specify a FILE pointer to read from. */ - curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source); + curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_cb); curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx); curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); @@ -156,12 +152,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); /* Send the message */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Free the list of recipients */ curl_slist_free_all(recipients); @@ -172,5 +168,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/smtp-tls.c b/docs/examples/smtp-tls.c index 4f7379529c1e..3b622859caed 100644 --- a/docs/examples/smtp-tls.c +++ b/docs/examples/smtp-tls.c @@ -21,14 +21,13 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Send SMTP email using implicit TLS * */ - #include #include + #include /* This is a simple example showing how to send mail using libcurl's SMTP @@ -39,9 +38,9 @@ * Note that this example requires libcurl 7.20.0 or above. */ -#define FROM_MAIL "" -#define TO_MAIL "" -#define CC_MAIL "" +#define FROM_MAIL "" +#define TO_MAIL "" +#define CC_MAIL "" static const char *payload_text = "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n" @@ -61,38 +60,35 @@ struct upload_status { size_t bytes_read; }; -static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp) +static size_t read_cb(char *ptr, size_t size, size_t nmemb, void *userp) { struct upload_status *upload_ctx = (struct upload_status *)userp; const char *data; size_t room = size * nmemb; + size_t len; - if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) { + if((size == 0) || (nmemb == 0) || ((size * nmemb) < 1)) { return 0; } data = &payload_text[upload_ctx->bytes_read]; - if(data) { - size_t len = strlen(data); - if(room < len) - len = room; - memcpy(ptr, data, len); - upload_ctx->bytes_read += len; - - return len; - } + len = strlen(data); + if(room < len) + len = room; + memcpy(ptr, data, len); + upload_ctx->bytes_read += len; - return 0; + return len; } int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -148,7 +144,7 @@ int main(void) /* We are using a callback function to specify the payload (the headers and * body of the message). You could just use the CURLOPT_READDATA option to * specify a FILE pointer to read from. */ - curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source); + curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_cb); curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx); curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); @@ -159,12 +155,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); /* Send the message */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Free the list of recipients */ curl_slist_free_all(recipients); @@ -175,5 +171,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/smtp-vrfy.c b/docs/examples/smtp-vrfy.c index 33d439ec9c43..4d5a8ad60135 100644 --- a/docs/examples/smtp-vrfy.c +++ b/docs/examples/smtp-vrfy.c @@ -21,14 +21,13 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ - /* * Verify an SMTP email address * */ - #include #include + #include /* This is a simple example showing how to verify an email address from an @@ -46,9 +45,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -62,12 +61,12 @@ int main(void) curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients); /* Perform the VRFY */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* Free the list of recipients */ curl_slist_free_all(recipients); @@ -83,5 +82,5 @@ int main(void) curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/sslbackend.c b/docs/examples/sslbackend.c index fd2b57534e65..5615bec72dc6 100644 --- a/docs/examples/sslbackend.c +++ b/docs/examples/sslbackend.c @@ -38,7 +38,7 @@ * SSL backend has to be configured). * * **** This example only works with libcurl 7.56.0 and later! **** -*/ + */ int main(int argc, char **argv) { diff --git a/docs/examples/synctime.c b/docs/examples/synctime.c index da2c7ea0f362..6209ebc314de 100644 --- a/docs/examples/synctime.c +++ b/docs/examples/synctime.c @@ -56,69 +56,62 @@ * This software synchronises your computer clock only when you issue * it with --synctime. By default, it only display the webserver's clock. */ +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* for _snprintf(), fopen(), gmtime(), + localtime(), sscanf() */ +#endif +#endif #include +#include +#include -#ifndef _WIN32 -int main(void) { printf("Platform not supported.\n"); return 1; } -#else +#include +#ifdef _WIN32 #if (defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0602)) || \ - defined(WINAPI_FAMILY) + defined(WINAPI_FAMILY) # include -# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \ +# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \ !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) # define CURL_WINDOWS_UWP # endif -#endif - -#ifdef CURL_WINDOWS_UWP -int main(void) { printf("Platform not supported.\n"); return 1; } -#else - -#include - -#include - #include +#endif +#endif #if defined(_MSC_VER) && (_MSC_VER < 1900) #define snprintf _snprintf #endif -#define MAX_STRING 256 -#define MAX_STRING1 MAX_STRING + 1 - #define SYNCTIME_UA "synctime/1.0" struct conf { - char http_proxy[MAX_STRING1]; - char proxy_user[MAX_STRING1]; - char timeserver[MAX_STRING1]; + char http_proxy[256]; + char proxy_user[256]; + char timeserver[256]; }; -static const char DefaultTimeServer[3][MAX_STRING1] = -{ - "https://nist.time.gov/", - "https://www.google.com/" -}; - -static const char *DayStr[] = { - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; -static const char *MthStr[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - static int ShowAllHeader; static int AutoSyncTime; +#if defined(_WIN32) && !defined(CURL_WINDOWS_UWP) static SYSTEMTIME SYSTime; static SYSTEMTIME LOCALTime; -#define HTTP_COMMAND_HEAD 0 -#define HTTP_COMMAND_GET 1 +static const char *DayStr[] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; +static const char *MthStr[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; +#endif + +#define HTTP_COMMAND_HEAD 0 +#define HTTP_COMMAND_GET 1 -static size_t SyncTime_CURL_WriteOutput(void *ptr, size_t size, size_t nmemb, - void *stream) +static size_t write_cb(void *ptr, size_t size, size_t nmemb, void *stream) { fwrite(ptr, size, nmemb, stream); return nmemb * size; @@ -128,8 +121,6 @@ static size_t SyncTime_CURL_WriteOutput(void *ptr, size_t size, size_t nmemb, static size_t SyncTime_CURL_WriteHeader(void *ptr, size_t size, size_t nmemb, void *stream) { - char TmpStr1[26], TmpStr2[26]; - (void)stream; if(ShowAllHeader == 1) @@ -140,6 +131,8 @@ static size_t SyncTime_CURL_WriteHeader(void *ptr, size_t size, size_t nmemb, fprintf(stderr, "HTTP Server. %.*s", (int)nmemb, (char *)ptr); if(AutoSyncTime == 1) { +#if defined(_WIN32) && !defined(CURL_WINDOWS_UWP) + char TmpStr1[26], TmpStr2[26]; int RetVal = 0; char *field = ptr; *TmpStr1 = 0; @@ -154,18 +147,19 @@ static size_t SyncTime_CURL_WriteHeader(void *ptr, size_t size, size_t nmemb, if(RetVal == 7) { int i; - SYSTime.wMilliseconds = 500; /* adjust to midpoint, 0.5 sec */ + SYSTime.wMilliseconds = 500; /* adjust to midpoint, 0.5 sec */ for(i = 0; i < 12; i++) { if(strcmp(MthStr[i], TmpStr2) == 0) { SYSTime.wMonth = (WORD)(i + 1); break; } } - AutoSyncTime = 3; /* Computer clock is adjusted */ + AutoSyncTime = 3; /* Computer clock is adjusted */ } else { - AutoSyncTime = 0; /* Error in sscanf() fields conversion */ + AutoSyncTime = 0; /* Error in sscanf() fields conversion */ } +#endif } } @@ -187,7 +181,7 @@ static void SyncTime_CURL_Init(CURL *curl, const char *proxy_port, curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, proxy_user_password); curl_easy_setopt(curl, CURLOPT_USERAGENT, SYNCTIME_UA); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, SyncTime_CURL_WriteOutput); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, SyncTime_CURL_WriteHeader); } @@ -195,7 +189,7 @@ static CURLcode SyncTime_CURL_Fetch(CURL *curl, const char *URL_Str, const char *OutFileName, int HttpGetBody) { FILE *outfile; - CURLcode res; + CURLcode result; outfile = NULL; if(HttpGetBody == HTTP_COMMAND_HEAD) @@ -206,10 +200,10 @@ static CURLcode SyncTime_CURL_Fetch(CURL *curl, const char *URL_Str, } curl_easy_setopt(curl, CURLOPT_URL, URL_Str); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); if(outfile) fclose(outfile); - return res; /* (CURLE_OK) */ + return result; /* CURLE_OK */ } static void showUsage(void) @@ -232,34 +226,25 @@ static void showUsage(void) return; } -static int conf_init(struct conf *conf) -{ - int i; - - *conf->http_proxy = 0; - for(i = 0; i < MAX_STRING1; i++) - conf->proxy_user[i] = 0; /* Clean up password from memory */ - *conf->timeserver = 0; - return 1; -} - int main(int argc, char *argv[]) { - CURLcode res; + CURLcode result; CURL *curl; - struct conf conf[1]; + struct conf conf; int RetValue; - ShowAllHeader = 0; /* Do not show HTTP Header */ - AutoSyncTime = 0; /* Do not synchronise computer clock */ - RetValue = 0; /* Successful Exit */ - conf_init(conf); + ShowAllHeader = 0; /* Do not show HTTP Header */ + AutoSyncTime = 0; /* Do not synchronise computer clock */ + RetValue = 0; /* Successful Exit */ + + memset(&conf, 0, sizeof(conf)); if(argc > 1) { int OptionIndex = 1; while(OptionIndex < argc) { if(strncmp(argv[OptionIndex], "--server=", 9) == 0) - snprintf(conf->timeserver, MAX_STRING, "%s", &argv[OptionIndex][9]); + snprintf(conf.timeserver, sizeof(conf.timeserver) - 1, "%s", + &argv[OptionIndex][9]); if(strcmp(argv[OptionIndex], "--showall") == 0) ShowAllHeader = 1; @@ -268,13 +253,15 @@ int main(int argc, char *argv[]) AutoSyncTime = 1; if(strncmp(argv[OptionIndex], "--proxy-user=", 13) == 0) - snprintf(conf->proxy_user, MAX_STRING, "%s", &argv[OptionIndex][13]); + snprintf(conf.proxy_user, sizeof(conf.proxy_user) - 1, "%s", + &argv[OptionIndex][13]); if(strncmp(argv[OptionIndex], "--proxy=", 8) == 0) - snprintf(conf->http_proxy, MAX_STRING, "%s", &argv[OptionIndex][8]); + snprintf(conf.http_proxy, sizeof(conf.http_proxy) - 1, "%s", + &argv[OptionIndex][8]); if((strcmp(argv[OptionIndex], "--help") == 0) || - (strcmp(argv[OptionIndex], "/?") == 0)) { + (strcmp(argv[OptionIndex], "/?") == 0)) { showUsage(); return 0; } @@ -282,13 +269,14 @@ int main(int argc, char *argv[]) } } - if(*conf->timeserver == 0) /* Use default server for time information */ - snprintf(conf->timeserver, MAX_STRING, "%s", DefaultTimeServer[0]); + if(*conf.timeserver == 0) /* Use default server for time information */ + snprintf(conf.timeserver, sizeof(conf.timeserver) - 1, "%s", + "https://www.ntp.org/"); /* Init CURL before usage */ - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -302,7 +290,7 @@ int main(int argc, char *argv[]) char timeBuf[61]; char tzoneBuf[16]; - SyncTime_CURL_Init(curl, conf->http_proxy, conf->proxy_user); + SyncTime_CURL_Init(curl, conf.http_proxy, conf.proxy_user); /* Calculating time diff between GMT and localtime */ tt = time(0); @@ -311,35 +299,35 @@ int main(int argc, char *argv[]) gmt = gmtime(&tt); tt_gmt = mktime(gmt); tzonediffFloat = difftime(tt_local, tt_gmt); - tzonediffWord = (int)(tzonediffFloat/3600.0); + tzonediffWord = (int)(tzonediffFloat / 3600.0); - if(tzonediffWord == (int)(tzonediffFloat/3600.0)) + if(tzonediffWord == (int)(tzonediffFloat / 3600.0)) snprintf(tzoneBuf, sizeof(tzoneBuf), "%+03d'00'", tzonediffWord); else snprintf(tzoneBuf, sizeof(tzoneBuf), "%+03d'30'", tzonediffWord); +#if defined(_WIN32) && !defined(CURL_WINDOWS_UWP) /* Get current system time and local time */ GetSystemTime(&SYSTime); GetLocalTime(&LOCALTime); snprintf(timeBuf, 60, "%s, %02d %s %04d %02d:%02d:%02d.%03d, ", DayStr[LOCALTime.wDayOfWeek], LOCALTime.wDay, - MthStr[LOCALTime.wMonth-1], LOCALTime.wYear, - LOCALTime.wHour, LOCALTime.wMinute, LOCALTime.wSecond, - LOCALTime.wMilliseconds); + MthStr[LOCALTime.wMonth - 1], LOCALTime.wYear, LOCALTime.wHour, + LOCALTime.wMinute, LOCALTime.wSecond, LOCALTime.wMilliseconds); +#endif - fprintf(stderr, "Fetch: %s\n\n", conf->timeserver); + fprintf(stderr, "Fetch: %s\n\n", conf.timeserver); fprintf(stderr, "Before HTTP. Date: %s%s\n\n", timeBuf, tzoneBuf); /* HTTP HEAD command to the Webserver */ - SyncTime_CURL_Fetch(curl, conf->timeserver, "index.htm", - HTTP_COMMAND_HEAD); + SyncTime_CURL_Fetch(curl, conf.timeserver, "index.htm", HTTP_COMMAND_HEAD); +#if defined(_WIN32) && !defined(CURL_WINDOWS_UWP) GetLocalTime(&LOCALTime); snprintf(timeBuf, 60, "%s, %02d %s %04d %02d:%02d:%02d.%03d, ", DayStr[LOCALTime.wDayOfWeek], LOCALTime.wDay, - MthStr[LOCALTime.wMonth-1], LOCALTime.wYear, - LOCALTime.wHour, LOCALTime.wMinute, LOCALTime.wSecond, - LOCALTime.wMilliseconds); + MthStr[LOCALTime.wMonth - 1], LOCALTime.wYear, LOCALTime.wHour, + LOCALTime.wMinute, LOCALTime.wSecond, LOCALTime.wMilliseconds); fprintf(stderr, "\nAfter HTTP. Date: %s%s\n", timeBuf, tzoneBuf); if(AutoSyncTime == 3) { @@ -353,15 +341,16 @@ int main(int argc, char *argv[]) GetLocalTime(&LOCALTime); snprintf(timeBuf, 60, "%s, %02d %s %04d %02d:%02d:%02d.%03d, ", DayStr[LOCALTime.wDayOfWeek], LOCALTime.wDay, - MthStr[LOCALTime.wMonth-1], LOCALTime.wYear, + MthStr[LOCALTime.wMonth - 1], LOCALTime.wYear, LOCALTime.wHour, LOCALTime.wMinute, LOCALTime.wSecond, LOCALTime.wMilliseconds); fprintf(stderr, "\nNew System's Date: %s%s\n", timeBuf, tzoneBuf); } } +#endif /* Cleanup before exit */ - conf_init(conf); + memset(&conf, 0, sizeof(conf)); curl_easy_cleanup(curl); } @@ -369,5 +358,3 @@ int main(int argc, char *argv[]) return RetValue; } -#endif /* CURL_WINDOWS_UWP */ -#endif /* _WIN32 */ diff --git a/docs/examples/threaded-ssl.c b/docs/examples/threaded.c similarity index 66% rename from docs/examples/threaded-ssl.c rename to docs/examples/threaded.c index 5d984a670ab9..9eeffa78f6de 100644 --- a/docs/examples/threaded-ssl.c +++ b/docs/examples/threaded.c @@ -22,14 +22,13 @@ * ***************************************************************************/ /* - * Show the required mutex callback setups for GnuTLS and OpenSSL when using - * libcurl multi-threaded. + * A multi-threaded program using pthreads to fetch several files at once * */ /* A multi-threaded example that uses pthreads and fetches 4 remote files at * once over HTTPS. * - * Recent versions of OpenSSL and GnuTLS are thread safe by design, assuming + * Recent versions of OpenSSL and GnuTLS are thread-safe by design, assuming * support for the underlying OS threading API is built-in. Older revisions * of this example demonstrated locking callbacks for the SSL library, which * are no longer necessary. An older revision with callbacks can be found at @@ -40,31 +39,33 @@ /* Also requires TLS support to run */ #include + #include + #include #define NUMT 4 -/* List of URLs to fetch.*/ -static const char * const urls[]= { - "https://www.example.com/", - "https://www2.example.com/", - "https://www3.example.com/", - "https://www4.example.com/", +/* List of URLs to fetch. */ +static const char * const urls[NUMT] = { + "https://curl.se/", + "ftp://example.com/", + "https://example.net/", + "www.example" }; -static void *pull_one_url(void *pindex) +struct targ { + const char *url; +}; + +static void *pull_one_url(void *p) { CURL *curl; curl = curl_easy_init(); if(curl) { - int i = *(int *)pindex; - curl_easy_setopt(curl, CURLOPT_URL, urls[i]); - /* this example does not verify the server's certificate, which means we - might be downloading stuff from an impostor */ - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); + struct targ *targ = p; + curl_easy_setopt(curl, CURLOPT_URL, targ->url); (void)curl_easy_perform(curl); /* ignores error */ curl_easy_cleanup(curl); } @@ -72,26 +73,33 @@ static void *pull_one_url(void *pindex) return NULL; } -int main(int argc, char **argv) +/* + int pthread_create(pthread_t *new_thread_ID, + const pthread_attr_t *attr, + void * (*start_func)(void *), void *arg); +*/ + +int main(void) { - CURLcode res; + CURLcode result; pthread_t tid[NUMT]; + struct targ targs[NUMT]; int i; - (void)argc; - (void)argv; /* Must initialize libcurl before any threads are started */ - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; for(i = 0; i < NUMT; i++) { - int error = pthread_create(&tid[i], - NULL, /* default attributes please */ - pull_one_url, - (void *)&i); + int error; + targs[i].url = urls[i]; + error = pthread_create(&tid[i], + NULL, /* default attributes please */ + pull_one_url, + (void *)&targs[i]); if(error) - fprintf(stderr, "Couldn't run thread number %d, errno %d\n", i, error); + fprintf(stderr, "Could not run thread number %d, errno %d\n", i, error); else fprintf(stderr, "Thread %d, gets %s\n", i, urls[i]); } diff --git a/docs/examples/unixsocket.c b/docs/examples/unixsocket.c index 738ffc2c972f..4a1a2937d6ce 100644 --- a/docs/examples/unixsocket.c +++ b/docs/examples/unixsocket.c @@ -42,9 +42,9 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -56,16 +56,16 @@ int main(void) curl_easy_setopt(curl, CURLOPT_UNIX_SOCKET_PATH, PATH); #endif - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/url2file.c b/docs/examples/url2file.c index 8e9e01db15df..0c9c5880f78c 100644 --- a/docs/examples/url2file.c +++ b/docs/examples/url2file.c @@ -25,12 +25,18 @@ * Download a given URL into a local file named page.out. * */ +#ifdef _MSC_VER +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* for fopen() */ +#endif +#endif + #include #include #include -static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream) +static size_t write_cb(void *ptr, size_t size, size_t nmemb, void *stream) { size_t written = fwrite(ptr, size, nmemb, (FILE *)stream); return written; @@ -40,56 +46,56 @@ int main(int argc, char *argv[]) { static const char *pagefilename = "page.out"; - CURLcode res; - CURL *curl_handle; + CURLcode result; + CURL *curl; if(argc < 2) { printf("Usage: %s \n", argv[0]); return 1; } - res = curl_global_init(CURL_GLOBAL_ALL); - if(res) { + result = curl_global_init(CURL_GLOBAL_ALL); + if(result) { fprintf(stderr, "Could not init curl\n"); - return (int)res; + return (int)result; } /* init the curl session */ - curl_handle = curl_easy_init(); - if(curl_handle) { + curl = curl_easy_init(); + if(curl) { FILE *pagefile; /* set URL to get here */ - curl_easy_setopt(curl_handle, CURLOPT_URL, argv[1]); + curl_easy_setopt(curl, CURLOPT_URL, argv[1]); /* Switch on full protocol/debug output while testing */ - curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L); + curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); /* disable progress meter, set to 0L to enable it */ - curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1L); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L); /* send all data to this function */ - curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); /* open the file */ pagefile = fopen(pagefilename, "wb"); if(pagefile) { /* write the page body to this file handle */ - curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, pagefile); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, pagefile); /* get it! */ - res = curl_easy_perform(curl_handle); + result = curl_easy_perform(curl); /* close the header file */ fclose(pagefile); } /* cleanup curl stuff */ - curl_easy_cleanup(curl_handle); + curl_easy_cleanup(curl); } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/urlapi.c b/docs/examples/urlapi.c index 82ef3e19aab9..4d6c6444bd1d 100644 --- a/docs/examples/urlapi.c +++ b/docs/examples/urlapi.c @@ -38,11 +38,11 @@ int main(void) CURLU *urlp; CURLUcode uc; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; - /* init Curl URL */ + /* init curl URL */ urlp = curl_url(); uc = curl_url_set(urlp, CURLUPART_URL, "http://example.com/path/index.html", 0); @@ -62,16 +62,16 @@ int main(void) /* only allow HTTP, TFTP and SFTP */ curl_easy_setopt(curl, CURLOPT_PROTOCOLS_STR, "http,tftp,sftp"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); } cleanup: curl_url_cleanup(urlp); curl_easy_cleanup(curl); curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/usercertinmem.c b/docs/examples/usercertinmem.c index c53fcde9cbce..6c782647c7de 100644 --- a/docs/examples/usercertinmem.c +++ b/docs/examples/usercertinmem.c @@ -38,9 +38,9 @@ #endif #include -#include -#include + #include + #include #if defined(__GNUC__) || defined(__clang__) @@ -114,7 +114,7 @@ static CURLcode sslctx_function(CURL *curl, void *sslctx, void *pointer) } /* tell SSL to use the X509 certificate */ - ret = SSL_CTX_use_certificate((SSL_CTX*)sslctx, cert); + ret = SSL_CTX_use_certificate((SSL_CTX *)sslctx, cert); if(ret != 1) { printf("Use certificate failed\n"); } @@ -132,7 +132,7 @@ static CURLcode sslctx_function(CURL *curl, void *sslctx, void *pointer) } /* tell SSL to use the RSA key from memory */ - ret = SSL_CTX_use_RSAPrivateKey((SSL_CTX*)sslctx, rsa); + ret = SSL_CTX_use_RSAPrivateKey((SSL_CTX *)sslctx, rsa); if(ret != 1) { printf("Use Key failed\n"); } @@ -156,52 +156,52 @@ static CURLcode sslctx_function(CURL *curl, void *sslctx, void *pointer) int main(void) { - CURL *ch; - - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; - - ch = curl_easy_init(); - if(ch) { - curl_easy_setopt(ch, CURLOPT_VERBOSE, 0L); - curl_easy_setopt(ch, CURLOPT_HEADER, 0L); - curl_easy_setopt(ch, CURLOPT_NOPROGRESS, 1L); - curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1L); - curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, writefunction); - curl_easy_setopt(ch, CURLOPT_WRITEDATA, stdout); - curl_easy_setopt(ch, CURLOPT_HEADERFUNCTION, writefunction); - curl_easy_setopt(ch, CURLOPT_HEADERDATA, stderr); - curl_easy_setopt(ch, CURLOPT_SSLCERTTYPE, "PEM"); + CURL *curl; + + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; + + curl = curl_easy_init(); + if(curl) { + curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L); + curl_easy_setopt(curl, CURLOPT_HEADER, 0L); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L); + curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunction); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, stdout); + curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, writefunction); + curl_easy_setopt(curl, CURLOPT_HEADERDATA, stderr); + curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM"); /* both VERIFYPEER and VERIFYHOST are set to 0 in this case because there is no CA certificate */ + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); - curl_easy_setopt(ch, CURLOPT_SSL_VERIFYPEER, 0L); - curl_easy_setopt(ch, CURLOPT_SSL_VERIFYHOST, 0L); - curl_easy_setopt(ch, CURLOPT_URL, "https://www.example.com/"); - curl_easy_setopt(ch, CURLOPT_SSLKEYTYPE, "PEM"); + curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/"); + curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, "PEM"); /* first try: retrieve page without user certificate and key -> fails */ - res = curl_easy_perform(ch); - if(res == CURLE_OK) + result = curl_easy_perform(curl); + if(result == CURLE_OK) printf("*** transfer succeeded ***\n"); else printf("*** transfer failed ***\n"); - /* second try: retrieve page using user certificate and key -> succeeds + /* second try: retrieve page using user certificate and key -> succeeds to * load the certificate and key by installing a function doing * the necessary "modifications" to the SSL CONTEXT just before link init */ - curl_easy_setopt(ch, CURLOPT_SSL_CTX_FUNCTION, sslctx_function); - res = curl_easy_perform(ch); - if(res == CURLE_OK) + curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, sslctx_function); + result = curl_easy_perform(curl); + if(result == CURLE_OK) printf("*** transfer succeeded ***\n"); else printf("*** transfer failed ***\n"); - curl_easy_cleanup(ch); + curl_easy_cleanup(curl); } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/websocket-cb.c b/docs/examples/websocket-cb.c index aa81d89ab126..defde4c0fe48 100644 --- a/docs/examples/websocket-cb.c +++ b/docs/examples/websocket-cb.c @@ -28,13 +28,13 @@ #include #include -static size_t writecb(char *b, size_t size, size_t nitems, void *p) +static size_t write_cb(char *b, size_t size, size_t nitems, void *p) { - CURL *easy = p; + CURL *curl = p; size_t i; - const struct curl_ws_frame *frame = curl_ws_meta(easy); - fprintf(stderr, "Type: %s\n", frame->flags & CURLWS_BINARY ? - "binary" : "text"); + const struct curl_ws_frame *frame = curl_ws_meta(curl); + fprintf(stderr, "Type: %s\n", + frame->flags & CURLWS_BINARY ? "binary" : "text"); fprintf(stderr, "Bytes: %u", (unsigned int)(nitems * size)); for(i = 0; i < nitems; i++) fprintf(stderr, "%02x ", (unsigned char)b[i]); @@ -45,28 +45,28 @@ int main(void) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, "wss://example.com"); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writecb); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); /* pass the easy handle to the callback */ curl_easy_setopt(curl, CURLOPT_WRITEDATA, curl); - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/websocket-updown.c b/docs/examples/websocket-updown.c index f95c151cacd1..8cbb938e9dbe 100644 --- a/docs/examples/websocket-updown.c +++ b/docs/examples/websocket-updown.c @@ -29,14 +29,14 @@ #include #include -static size_t writecb(char *b, size_t size, size_t nitems, void *p) +static size_t write_cb(char *b, size_t size, size_t nitems, void *p) { - CURL *easy = p; + CURL *curl = p; size_t i; unsigned int blen = (unsigned int)(nitems * size); - const struct curl_ws_frame *frame = curl_ws_meta(easy); - fprintf(stderr, "Type: %s\n", frame->flags & CURLWS_BINARY ? - "binary" : "text"); + const struct curl_ws_frame *frame = curl_ws_meta(curl); + fprintf(stderr, "Type: %s\n", + frame->flags & CURLWS_BINARY ? "binary" : "text"); if(frame->flags & CURLWS_BINARY) { fprintf(stderr, "Bytes: %u", blen); for(i = 0; i < nitems; i++) @@ -49,13 +49,13 @@ static size_t writecb(char *b, size_t size, size_t nitems, void *p) } struct read_ctx { - CURL *easy; + CURL *curl; char buf[1024]; size_t blen; size_t nsent; }; -static size_t readcb(char *buf, size_t nitems, size_t buflen, void *p) +static size_t read_cb(char *buf, size_t nitems, size_t buflen, void *p) { struct read_ctx *ctx = p; size_t len = nitems * buflen; @@ -63,9 +63,9 @@ static size_t readcb(char *buf, size_t nitems, size_t buflen, void *p) CURLcode result; if(!ctx->nsent) { - /* On first call, set the FRAME information to be used (it defaults - * to CURLWS_BINARY otherwise). */ - result = curl_ws_start_frame(ctx->easy, CURLWS_TEXT, + /* On first call, set the FRAME information to be used (it defaults to + * CURLWS_BINARY otherwise). */ + result = curl_ws_start_frame(ctx->curl, CURLWS_TEXT, (curl_off_t)ctx->blen); if(result) { fprintf(stderr, "error starting frame: %d\n", result); @@ -85,44 +85,43 @@ static size_t readcb(char *buf, size_t nitems, size_t buflen, void *p) int main(int argc, const char *argv[]) { - CURL *easy; + CURL *curl; struct read_ctx rctx; const char *payload = "Hello, friend!"; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; memset(&rctx, 0, sizeof(rctx)); - easy = curl_easy_init(); - if(easy) { + curl = curl_easy_init(); + if(curl) { if(argc == 2) - curl_easy_setopt(easy, CURLOPT_URL, argv[1]); + curl_easy_setopt(curl, CURLOPT_URL, argv[1]); else - curl_easy_setopt(easy, CURLOPT_URL, "wss://example.com"); + curl_easy_setopt(curl, CURLOPT_URL, "wss://example.com"); - curl_easy_setopt(easy, CURLOPT_WRITEFUNCTION, writecb); - curl_easy_setopt(easy, CURLOPT_WRITEDATA, easy); - curl_easy_setopt(easy, CURLOPT_READFUNCTION, readcb); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, curl); + curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_cb); /* tell curl that we want to send the payload */ - rctx.easy = easy; + rctx.curl = curl; rctx.blen = strlen(payload); memcpy(rctx.buf, payload, rctx.blen); - curl_easy_setopt(easy, CURLOPT_READDATA, &rctx); - curl_easy_setopt(easy, CURLOPT_UPLOAD, 1L); + curl_easy_setopt(curl, CURLOPT_READDATA, &rctx); + curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); - - /* Perform the request, res gets the return code */ - res = curl_easy_perform(easy); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ - curl_easy_cleanup(easy); + curl_easy_cleanup(curl); } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/websocket.c b/docs/examples/websocket.c index 0063f1b59c63..2fa53028a841 100644 --- a/docs/examples/websocket.c +++ b/docs/examples/websocket.c @@ -39,27 +39,27 @@ static CURLcode ping(CURL *curl, const char *send_payload) { - CURLcode res = CURLE_OK; + CURLcode result = CURLE_OK; const char *buf = send_payload; size_t sent, blen = strlen(send_payload); while(blen) { - res = curl_ws_send(curl, buf, blen, &sent, 0, CURLWS_PING); - if(!res) { + result = curl_ws_send(curl, buf, blen, &sent, 0, CURLWS_PING); + if(!result) { buf += sent; /* deduct what was sent */ blen -= sent; } - else if(res == CURLE_AGAIN) { /* blocked on sending */ + else if(result == CURLE_AGAIN) { /* blocked on sending */ fprintf(stderr, "ws: sent PING blocked, waiting a second\n"); - sleep(1); /* either select() on socket or max timeout would - be good here. */ + sleep(1); /* either select() on socket or max timeout would + be good here. */ } else /* real error sending */ break; } - if(!res) + if(!result) fprintf(stderr, "ws: sent PING with payload\n"); - return res; + return result; } static CURLcode recv_pong(CURL *curl, const char *expected_payload) @@ -67,11 +67,11 @@ static CURLcode recv_pong(CURL *curl, const char *expected_payload) size_t rlen = 0; const struct curl_ws_frame *meta; char buffer[256]; - CURLcode res; + CURLcode result; retry: - res = curl_ws_recv(curl, buffer, sizeof(buffer), &rlen, &meta); - if(!res) { + result = curl_ws_recv(curl, buffer, sizeof(buffer), &rlen, &meta); + if(!result) { /* on small PING content, this example assumes the complete * PONG content arrives in one go. Larger frames will arrive * in chunks, however. */ @@ -85,8 +85,7 @@ static CURLcode recv_pong(CURL *curl, const char *expected_payload) same ? "same" : "different"); } else if(meta->flags & CURLWS_TEXT) { - fprintf(stderr, "ws: received TEXT frame '%.*s'\n", (int)rlen, - buffer); + fprintf(stderr, "ws: received TEXT frame '%.*s'\n", (int)rlen, buffer); } else if(meta->flags & CURLWS_BINARY) { fprintf(stderr, "ws: received BINARY frame of %u bytes\n", @@ -99,16 +98,16 @@ static CURLcode recv_pong(CURL *curl, const char *expected_payload) goto retry; } } - else if(res == CURLE_AGAIN) { /* blocked on receiving */ + else if(result == CURLE_AGAIN) { /* blocked on receiving */ fprintf(stderr, "ws: PONG not there yet, waiting a second\n"); - sleep(1); /* either select() on socket or max timeout would - be good here. */ + sleep(1); /* either select() on socket or max timeout would + be good here. */ goto retry; } - if(res) + if(result) fprintf(stderr, "ws: curl_ws_recv returned %u, received %u\n", - (unsigned int)res, (unsigned int)rlen); - return res; + (unsigned int)result, (unsigned int)rlen); + return result; } /* close the connection */ @@ -120,28 +119,28 @@ static void websocket_close(CURL *curl) static CURLcode websocket(CURL *curl) { - CURLcode res; + CURLcode result; int i = 0; do { - res = ping(curl, "foobar"); - if(res) + result = ping(curl, "foobar"); + if(result) break; - res = recv_pong(curl, "foobar"); - if(res) + result = recv_pong(curl, "foobar"); + if(result) break; sleep(1); } while(i++ < 10); websocket_close(curl); - return res; + return result; } int main(int argc, const char *argv[]) { CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; curl = curl_easy_init(); if(curl) { @@ -152,20 +151,20 @@ int main(int argc, const char *argv[]) curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 2L); /* websocket style */ - /* Perform the request, res gets the return code */ - res = curl_easy_perform(curl); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); else { /* connected and ready */ - res = websocket(curl); + result = websocket(curl); } /* always cleanup */ curl_easy_cleanup(curl); } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/examples/xmlstream.c b/docs/examples/xmlstream.c index 1131a3ce9e76..9122c491dc58 100644 --- a/docs/examples/xmlstream.c +++ b/docs/examples/xmlstream.c @@ -32,12 +32,12 @@ * gcc -Wall -I/usr/local/include xmlstream.c -lcurl -lexpat -o xmlstream * */ - #include #include #include #include + #include struct MemoryStruct { @@ -55,7 +55,7 @@ struct ParserStruct { static void startElement(void *userData, const XML_Char *name, const XML_Char **atts) { - struct ParserStruct *state = (struct ParserStruct *) userData; + struct ParserStruct *state = (struct ParserStruct *)userData; state->tags++; state->depth++; @@ -70,7 +70,7 @@ static void startElement(void *userData, const XML_Char *name, static void characterDataHandler(void *userData, const XML_Char *s, int len) { - struct ParserStruct *state = (struct ParserStruct *) userData; + struct ParserStruct *state = (struct ParserStruct *)userData; struct MemoryStruct *mem = &state->characters; char *ptr = realloc(mem->memory, mem->size + (unsigned long)len + 1); @@ -89,18 +89,18 @@ static void characterDataHandler(void *userData, const XML_Char *s, int len) static void endElement(void *userData, const XML_Char *name) { - struct ParserStruct *state = (struct ParserStruct *) userData; + struct ParserStruct *state = (struct ParserStruct *)userData; state->depth--; printf("%5lu %10lu %s\n", state->depth, state->characters.size, name); } -static size_t parseStreamCallback(void *contents, size_t length, size_t nmemb, - void *userp) +static size_t write_cb(void *contents, size_t length, size_t nmemb, + void *userp) { - XML_Parser parser = (XML_Parser) userp; + XML_Parser parser = (XML_Parser)userp; size_t real_size = length * nmemb; - struct ParserStruct *state = (struct ParserStruct *) XML_GetUserData(parser); + struct ParserStruct *state = (struct ParserStruct *)XML_GetUserData(parser); /* Only parse if we are not already in a failure state. */ if(state->ok && XML_Parse(parser, contents, (int)real_size, 0) == 0) { @@ -116,14 +116,14 @@ static size_t parseStreamCallback(void *contents, size_t length, size_t nmemb, int main(void) { - CURL *curl_handle; + CURL *curl; - CURLcode res = curl_global_init(CURL_GLOBAL_ALL); - if(res) - return (int)res; + CURLcode result = curl_global_init(CURL_GLOBAL_ALL); + if(result) + return (int)result; /* Initialize a libcurl handle. */ - curl_handle = curl_easy_init(); + curl = curl_easy_init(); if(curl) { XML_Parser parser; struct ParserStruct state; @@ -138,21 +138,21 @@ int main(void) XML_SetElementHandler(parser, startElement, endElement); XML_SetCharacterDataHandler(parser, characterDataHandler); - curl_easy_setopt(curl_handle, CURLOPT_URL, + curl_easy_setopt(curl, CURLOPT_URL, "https://www.w3schools.com/xml/simple.xml"); - curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, parseStreamCallback); - curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)parser); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)parser); printf("Depth Characters Closing Tag\n"); /* Perform the request and any follow-up parsing. */ - res = curl_easy_perform(curl_handle); - if(res != CURLE_OK) { + result = curl_easy_perform(curl); + if(result != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); } else if(state.ok) { - /* Expat requires one final call to finalize parsing. */ + /* Expat requiresult one final call to finalize parsing. */ if(XML_Parse(parser, NULL, 0, 1) == 0) { enum XML_Error error_code = XML_GetErrorCode(parser); fprintf(stderr, "Finalizing parsing failed with error code %d (%s).\n", @@ -168,10 +168,10 @@ int main(void) free(state.characters.memory); XML_ParserFree(parser); - curl_easy_cleanup(curl_handle); + curl_easy_cleanup(curl); } curl_global_cleanup(); - return (int)res; + return (int)result; } diff --git a/docs/internals/BUFQ.md b/docs/internals/BUFQ.md index 6028711d2c50..8136d588f6e9 100644 --- a/docs/internals/BUFQ.md +++ b/docs/internals/BUFQ.md @@ -14,7 +14,6 @@ to and read from. It manages read and write positions and has a maximum size. Its basic read/write functions have a similar signature and return code handling as many internal curl read and write ones. - ``` ssize_t Curl_bufq_write(struct bufq *q, const unsigned char *buf, size_t len, CURLcode *err); @@ -150,7 +149,6 @@ reports **full**, but one can **still** write. This option is necessary, if partial writes need to be avoided. It means that you need other checks to keep the `bufq` from growing ever larger and larger. - ## pools A `struct bufc_pool` may be used to create chunks for a `bufq` and keep spare diff --git a/docs/internals/BUFREF.md b/docs/internals/BUFREF.md index 9a8b506b561a..46f7ee6b3e50 100644 --- a/docs/internals/BUFREF.md +++ b/docs/internals/BUFREF.md @@ -54,10 +54,11 @@ specified as `NULL`: this is the case when the referenced buffer is static. if `buffer` is NULL, `length` must be zero. -## `memdup` +## `memdup0` ```c -CURLcode Curl_bufref_memdup(struct bufref *br, const void *data, size_t length); +CURLcode Curl_bufref_memdup0(struct bufref *br, const void *data, + size_t length); ``` Releases the previously referenced buffer, then duplicates the `length`-byte @@ -72,7 +73,15 @@ Returns `CURLE_OK` if successful, else `CURLE_OUT_OF_MEMORY`. ## `ptr` ```c -const unsigned char *Curl_bufref_ptr(const struct bufref *br); +const char *Curl_bufref_ptr(const struct bufref *br); +``` + +Returns a `const char *` to the referenced buffer. + +## `uptr` + +```c +const unsigned char *Curl_bufref_uptr(const struct bufref *br); ``` Returns a `const unsigned char *` to the referenced buffer. @@ -84,3 +93,12 @@ size_t Curl_bufref_len(const struct bufref *br); ``` Returns the stored length of the referenced buffer. + +## `dup` + +```c +char *Curl_bufref_dup(const struct bufref *br); +``` + +Returns a strdup() version of the buffer. Note that this assumes that the +bufref is null terminated. diff --git a/docs/internals/CHECKSRC.md b/docs/internals/CHECKSRC.md index 9c4f1428791e..091a4d3107e6 100644 --- a/docs/internals/CHECKSRC.md +++ b/docs/internals/CHECKSRC.md @@ -76,7 +76,8 @@ warnings are: - `EXCLAMATIONSPACE`: space found after exclamations mark -- `FOPENMODE`: `curlx_fopen()` needs a macro for the mode string, use it +- `FOPENMODE`: `curlx_fopen()`, `curlx_freopen()` need a macro for the mode + string, use it - `INDENTATION`: detected a wrong start column for code. Note that this warning only checks some specific places and can certainly miss many bad @@ -106,7 +107,7 @@ warnings are: `sizeof(int)` style. - `SNPRINTF` - Found use of `snprintf()`. Since we use an internal replacement - with a different return code etc, we prefer `msnprintf()`. + with a different return code etc, we prefer `curl_msnprintf()`. - `SPACEAFTERPAREN`: there was a space after open parenthesis, `( text`. diff --git a/docs/internals/CLIENT-READERS.md b/docs/internals/CLIENT-READERS.md index 35caaa6bfc6d..bb94bba95f11 100644 --- a/docs/internals/CLIENT-READERS.md +++ b/docs/internals/CLIENT-READERS.md @@ -6,26 +6,41 @@ SPDX-License-Identifier: curl # curl client readers -Client readers is a design in the internals of libcurl, not visible in its public API. They were started -in curl v8.7.0. This document describes the concepts, its high level implementation and the motivations. +Client readers is a design in the internals of libcurl, not visible in its +public API. They were started in curl v8.7.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 **sent** to the server, the servers response is **received** by `libcurl` and then **written** to the client. +`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 **sent** to the server, the servers +response is **received** by `libcurl` and then **written** to the client. -With this naming established, client readers are concerned with providing data from the application to the server. Applications register callbacks via `CURLOPT_READFUNCTION`, data via `CURLOPT_POSTFIELDS` and other options to be used by `libcurl` when the request is send. +With this naming established, client readers are concerned with providing data +from the application to the server. Applications register callbacks via +`CURLOPT_READFUNCTION`, data via `CURLOPT_POSTFIELDS` and other options to be +used by `libcurl` when the request is send. ## Invoking -The transfer loop that sends and receives, is using `Curl_client_read()` to get more data to send for a transfer. If no specific reader has been installed yet, the default one that uses `CURLOPT_READFUNCTION` is added. The prototype is +The transfer loop that sends and receives, is using `Curl_client_read()` to get +more data to send for a transfer. If no specific reader has been installed yet, +the default one that uses `CURLOPT_READFUNCTION` is added. The prototype is ``` CURLcode Curl_client_read(struct Curl_easy *data, char *buf, size_t blen, size_t *nread, bool *eos); ``` -The arguments are the transfer to read for, a buffer to hold the read data, its length, the actual number of bytes placed into the buffer and the `eos` (*end of stream*) flag indicating that no more data is available. The `eos` flag may be set for a read amount, if that amount was the last. That way curl can avoid to read an additional time. +The arguments are the transfer to read for, a buffer to hold the read data, its +length, the actual number of bytes placed into the buffer and the `eos` (*end of +stream*) flag indicating that no more data is available. The `eos` flag may be +set for a read amount, if that amount was the last. That way curl can avoid to +read an additional time. -The implementation of `Curl_client_read()` uses a chain of *client reader* instances to get the data. This is similar to the design of *client writers*. The chain of readers allows processing of the data to send. +The implementation of `Curl_client_read()` uses a chain of *client reader* +instances to get the data. This is similar to the design of *client writers*. +The chain of readers allows processing of the data to send. The definition of a reader is: @@ -51,11 +66,17 @@ struct Curl_creader { }; ``` -`Curl_creader` is a reader instance with a `next` pointer to form the chain. It as a type `crt` which provides the implementation. The main callback is `do_read()` which provides the data to the caller. The others are for setup and tear down. `needs_rewind()` is explained further below. +`Curl_creader` is a reader instance with a `next` pointer to form the chain. +It as a type `crt` which provides the implementation. The main callback is +`do_read()` which provides the data to the caller. The others are for setup +and tear down. `needs_rewind()` is explained further below. ## Phases and Ordering -Since client readers may transform the data being read through the chain, the order in which they are called is relevant for the outcome. When a reader is created, it gets the `phase` property in which it operates. Reader phases are defined like: +Since client readers may transform the data being read through the chain, +the order in which they are called is relevant for the outcome. When a reader +is created, it gets the `phase` property in which it operates. Reader phases +are defined like: ``` typedef enum { @@ -67,65 +88,115 @@ typedef enum { } Curl_creader_phase; ``` -If a reader for phase `PROTOCOL` is added to the chain, it is always added *after* any `NET` or `TRANSFER_ENCODE` readers and *before* and `CONTENT_ENCODE` and `CLIENT` readers. If there is already a reader for the same phase, the new reader is added before the existing one(s). +If a reader for phase `PROTOCOL` is added to the chain, it is always added +*after* any `NET` or `TRANSFER_ENCODE` readers and *before* and +`CONTENT_ENCODE` and `CLIENT` readers. If there is already a reader for the +same phase, the new reader is added before the existing one(s). ### Example: `chunked` reader -In `http_chunks.c` a client reader for chunked uploads is implemented. This one operates at phase `CURL_CR_TRANSFER_ENCODE`. Any data coming from the reader "below" has the HTTP/1.1 chunk handling applied and returned to the caller. +In `http_chunks.c` a client reader for chunked uploads is implemented. This +one operates at phase `CURL_CR_TRANSFER_ENCODE`. Any data coming from the +reader "below" has the HTTP/1.1 chunk handling applied and returned to the +caller. -When this reader sees an `eos` from below, it generates the terminal chunk, adding trailers if provided by the application. When that last chunk is fully returned, it also sets `eos` to the caller. +When this reader sees an `eos` from below, it generates the terminal chunk, +adding trailers if provided by the application. When that last chunk is fully +returned, it also sets `eos` to the caller. ### Example: `lineconv` reader -In `sendf.c` a client reader that does line-end conversions is implemented. It operates at `CURL_CR_CONTENT_ENCODE` and converts any "\n" to "\r\n". This is used for FTP ASCII uploads or when the general `crlf` options has been set. +In `sendf.c` a client reader that does line-end conversions is implemented. It +operates at `CURL_CR_CONTENT_ENCODE` and converts any "\n" to "\r\n". This is +used for FTP ASCII uploads or when the general `crlf` options has been set. ### Example: `null` reader -Implemented in `sendf.c` for phase `CURL_CR_CLIENT`, this reader has the simple job of providing transfer bytes of length 0 to the caller, immediately indicating an `eos`. This reader is installed by HTTP for all GET/HEAD requests and when authentication is being negotiated. +Implemented in `sendf.c` for phase `CURL_CR_CLIENT`, this reader has the +simple job of providing transfer bytes of length 0 to the caller, immediately +indicating an `eos`. This reader is installed by HTTP for all GET/HEAD +requests and when authentication is being negotiated. ### Example: `buf` reader -Implemented in `sendf.c` for phase `CURL_CR_CLIENT`, this reader get a buffer pointer and a length and provides exactly these bytes. This one is used in HTTP for sending `postfields` provided by the application. +Implemented in `sendf.c` for phase `CURL_CR_CLIENT`, this reader get a buffer +pointer and a length and provides exactly these bytes. This one is used in +HTTP for sending `postfields` provided by the application. ## Request retries -Sometimes it is necessary to send a request with client data again. Transfer handling can inquire via `Curl_client_read_needs_rewind()` if a rewind (e.g. a reset of the client data) is necessary. This asks all installed readers if they need it and give `FALSE` of none does. +Sometimes it is necessary to send a request with client data again. Transfer +handling can inquire via `Curl_client_read_needs_rewind()` if a rewind (e.g. a +reset of the client data) is necessary. This asks all installed readers if +they need it and give `FALSE` of none does. ## Upload Size -Many protocols need to know the amount of bytes delivered by the client readers in advance. They may invoke `Curl_creader_total_length(data)` to retrieve that. However, not all reader chains know the exact value beforehand. In that case, the call returns `-1` for "unknown". +Many protocols need to know the amount of bytes delivered by the client +readers in advance. They may invoke `Curl_creader_total_length(data)` to +retrieve that. However, not all reader chains know the exact value beforehand. +In that case, the call returns `-1` for "unknown". -Even if the length of the "raw" data is known, the length that is send may not. Example: with option `--crlf` the uploaded content undergoes line-end conversion. The line converting reader does not know in advance how many newlines it may encounter. Therefore it must return `-1` for any positive raw content length. +Even if the length of the "raw" data is known, the length that is send may +not. Example: with option `--crlf` the uploaded content undergoes line-end +conversion. The line converting reader does not know in advance how many +newlines it may encounter. Therefore it must return `-1` for any positive raw +content length. -In HTTP, once the correct client readers are installed, the protocol asks the readers for the total length. If that is known, it can set `Content-Length:` accordingly. If not, it may choose to add an HTTP "chunked" reader. +In HTTP, once the correct client readers are installed, the protocol asks the +readers for the total length. If that is known, it can set `Content-Length:` +accordingly. If not, it may choose to add an HTTP "chunked" reader. -In addition, there is `Curl_creader_client_length(data)` which gives the total length as reported by the reader in phase `CURL_CR_CLIENT` without asking other readers that may transform the raw data. This is useful in estimating the size of an upload. The HTTP protocol uses this to determine if `Expect: 100-continue` shall be done. +In addition, there is `Curl_creader_client_length(data)` which gives the total +length as reported by the reader in phase `CURL_CR_CLIENT` without asking +other readers that may transform the raw data. This is useful in estimating +the size of an upload. The HTTP protocol uses this to determine if `Expect: +100-continue` shall be done. ## Resuming -Uploads can start at a specific offset, if so requested. The "resume from" that offset. This applies to the reader in phase `CURL_CR_CLIENT` that delivers the "raw" content. Resumption can fail if the installed reader does not support it or if the offset is too large. +Uploads can start at a specific offset, if so requested. The "resume from" +that offset. This applies to the reader in phase `CURL_CR_CLIENT` that +delivers the "raw" content. Resumption can fail if the installed reader does +not support it or if the offset is too large. -The total length reported by the reader changes when resuming. Example: resuming an upload of 100 bytes by 25 reports a total length of 75 afterwards. +The total length reported by the reader changes when resuming. Example: +resuming an upload of 100 bytes by 25 reports a total length of 75 afterwards. -If `resume_from()` is invoked twice, it is additive. There is currently no way to undo a resume. +If `resume_from()` is invoked twice, it is additive. There is currently no way +to undo a resume. ## Rewinding -When a request is retried, installed client readers are discarded and replaced by new ones. This works only if the new readers upload the same data. For many readers, this is not an issue. The "null" reader always does the same. Also the `buf` reader, initialized with the same buffer, does this. - -Readers operating on callbacks to the application need to "rewind" the underlying content. For example, when reading from a `FILE*`, the reader needs to `fseek()` to the beginning. The following methods are used: - -1. `Curl_creader_needs_rewind(data)`: tells if a rewind is necessary, given the current state of the reader chain. If nothing really has been read so far, this returns `FALSE`. -2. `Curl_creader_will_rewind(data)`: tells if the reader chain rewinds at the start of the next request. -3. `Curl_creader_set_rewind(data, TRUE)`: marks the reader chain for rewinding at the start of the next request. -4. `Curl_client_start(data)`: tells the readers that a new request starts and they need to rewind if requested. - +When a request is retried, installed client readers are discarded and replaced +by new ones. This works only if the new readers upload the same data. For many +readers, this is not an issue. The "null" reader always does the same. Also +the `buf` reader, initialized with the same buffer, does this. + +Readers operating on callbacks to the application need to "rewind" the +underlying content. For example, when reading from a `FILE*`, the reader needs +to `fseek()` to the beginning. The following methods are used: + +1. `Curl_creader_needs_rewind(data)`: tells if a rewind is necessary, given + the current state of the reader chain. If nothing really has been read so + far, this returns `FALSE`. +2. `Curl_creader_will_rewind(data)`: tells if the reader chain rewinds at + the start of the next request. +3. `Curl_creader_set_rewind(data, TRUE)`: marks the reader chain for rewinding + at the start of the next request. +4. `Curl_client_start(data)`: tells the readers that a new request starts and + they need to rewind if requested. ## Summary and Outlook -By adding the client reader interface, any protocol can control how/if it wants the curl transfer to send bytes for a request. The transfer loop becomes then blissfully ignorant of the specifics. +By adding the client reader interface, any protocol can control how/if it wants +the curl transfer to send bytes for a request. The transfer loop becomes then +blissfully ignorant of the specifics. -The protocols on the other hand no longer have to care to package data most efficiently. At any time, should more data be needed, it can be read from the client. This is used when sending HTTP requests headers to add as much request body data to the initial sending as there is room for. +The protocols on the other hand no longer have to care to package data most +efficiently. At any time, should more data be needed, it can be read from the +client. This is used when sending HTTP requests headers to add as much request +body data to the initial sending as there is room for. Future enhancements based on the client readers: * `expect-100` handling: place that into an HTTP specific reader at diff --git a/docs/internals/CLIENT-WRITERS.md b/docs/internals/CLIENT-WRITERS.md index 9f7197d22890..b07a562afbfb 100644 --- a/docs/internals/CLIENT-WRITERS.md +++ b/docs/internals/CLIENT-WRITERS.md @@ -6,24 +6,35 @@ SPDX-License-Identifier: curl # 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. +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. +`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. +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: +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, const char *buf, size_t blen); ``` -The `type` argument specifies what the bytes in `buf` actually are. The following bits are defined: +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 */ @@ -35,11 +46,15 @@ The `type` argument specifies what the bytes in `buf` actually are. The followin ``` 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 +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: +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 { @@ -60,11 +75,17 @@ struct Curl_cwriter { }; ``` -`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. +`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: +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 { @@ -76,15 +97,28 @@ typedef enum { } 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. +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 @@ -112,12 +146,23 @@ 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. +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. +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. +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. +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/internals/CODE_STYLE.md b/docs/internals/CODE_STYLE.md index 0d072c04c306..ee5bdbb5629d 100644 --- a/docs/internals/CODE_STYLE.md +++ b/docs/internals/CODE_STYLE.md @@ -24,8 +24,8 @@ need to copy the style already used in the source code and there are no particularly unusual rules in our set of rules. We also work hard on writing code that are warning-free on all the major -platforms and in general on as many platforms as possible. Code that obviously -causes warnings is not accepted as-is. +platforms and in general on as many platforms as possible. Code that causes +warnings is not accepted as-is. ## Readability @@ -334,14 +334,36 @@ This is the full list of functions generally banned. _access _mbscat _mbsncat + _open _tcscat _tcsdup _tcsncat + _tcsncpy _waccess _wcscat _wcsdup _wcsncat + _wfopen + _wfreopen + _wopen + accept + accept4 access + aprintf + atoi + atol + calloc + CreateFile + CreateFileA + CreateFileW + fclose + fdopen + fopen + fprintf + free + freeaddrinfo + freopen + getaddrinfo gets gmtime LoadLibrary @@ -351,10 +373,27 @@ This is the full list of functions generally banned. LoadLibraryExW LoadLibraryW localtime + malloc + mbstowcs + MoveFileEx + MoveFileExA + MoveFileExW + msnprintf + mvsnprintf + open + printf + realloc + recv + rename + send snprintf + socket + socketpair sprintf sscanf + stat strcat + strdup strerror strncat strncpy @@ -362,6 +401,15 @@ This is the full list of functions generally banned. strtok_r strtol strtoul + vaprintf + vfprintf + vprintf vsnprintf vsprintf + wcscpy wcsdup + wcsncpy + wcstombs + WSASocket + WSASocketA + WSASocketW diff --git a/docs/internals/CONNECTION-FILTERS.md b/docs/internals/CONNECTION-FILTERS.md index 09acc7ad9560..3fbb041a16d8 100644 --- a/docs/internals/CONNECTION-FILTERS.md +++ b/docs/internals/CONNECTION-FILTERS.md @@ -233,7 +233,7 @@ Users of `curl` may activate them by adding the name of the filter type to the of an HTTP/2 request, invoke curl with: ``` -> curl -v --trace-config ids,time,http/2 https://curl.se +> curl -v --trace-config ids,time,http/2 https://curl.se/ ``` Which gives you trace output with time information, transfer+connection ids @@ -260,7 +260,7 @@ into IPv4 and IPv6 and makes parallel attempts. The connection filter chain looks like this: ``` -* create connection for http://curl.se +* create connection for http://curl.se/ conn[curl.se] --> SETUP[TCP] --> HAPPY-EYEBALLS --> NULL * start connect conn[curl.se] --> SETUP[TCP] --> HAPPY-EYEBALLS --> NULL @@ -271,12 +271,17 @@ 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 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 to have happy eyeballing for QUIC: +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 to have happy eyeballing for QUIC: ``` -* create connection for --http3-only https://curl.se +* 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 @@ -292,7 +297,7 @@ 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 +* create connection for --http3 https://curl.se/ conn[curl.se] --> HTTPS-CONNECT --> NULL * start connect conn[curl.se] --> HTTPS-CONNECT --> NULL diff --git a/docs/internals/MQTT.md b/docs/internals/MQTT.md index 9b8d0efaae2d..acf7464be55c 100644 --- a/docs/internals/MQTT.md +++ b/docs/internals/MQTT.md @@ -12,7 +12,6 @@ A plain "GET" subscribes to the topic and prints all published messages. Doing a "POST" publishes the post data to the topic and exits. - ### Subscribing Command usage: @@ -26,9 +25,10 @@ Example subscribe: This sends an MQTT SUBSCRIBE packet for the topic `bedroom/temp` and listen in for incoming PUBLISH packets. -You can set the upkeep interval ms option to make curl send MQTT ping requests to the -server at an internal, to prevent the connection to get closed because of idleness. -You might then need to use the progress callback to cancel the operation. +You can set the upkeep interval ms option to make curl send MQTT ping requests +to the server at an internal, to prevent the connection to get closed because +of idleness. You might then need to use the progress callback to cancel the +operation. ### Publishing @@ -45,8 +45,8 @@ payload `75`. ## What does curl deliver as a response to a subscribe -Whenever a PUBLISH packet is received, curl outputs two bytes topic length (MSB | LSB), the topic followed by the -payload. +Whenever a PUBLISH packet is received, curl outputs two bytes topic length +(MSB | LSB), the topic followed by the payload. ## Caveats diff --git a/docs/internals/RATELIMITS.md b/docs/internals/RATELIMITS.md new file mode 100644 index 000000000000..af72211b7874 --- /dev/null +++ b/docs/internals/RATELIMITS.md @@ -0,0 +1,100 @@ + + +# Rate Limiting Transfers + +Rate limiting a transfer means that no more than "n bytes per second" +shall be sent or received. It can be set individually for both directions +via `CURLOPT_MAX_RECV_SPEED_LARGE` and `CURLOPT_MAX_SEND_SPEED_LARGE`. These +options may be adjusted for an ongoing transfer. + +### Implementation Base + +`ratelimit.[ch]` implements `struct Curl_rlimit` and functions to manage +such limits. It has the following properties: + +* `rate_per_sec`: how many "tokens" can be used per second, 0 for infinite. +* `tokens`: the currently available tokens to consume +* `burst_per_sec`: an upper limit on tokens available +* `ts`: the microsecond timestamp of the last tokens update +* `spare_us`: elapsed microseconds that have not counted yet for a token update +* `blocked`: if the limit is blocked + +Tokens can be *drained* from an `rlimit`. This reduces `tokens`, even to +negative values. To enforce the limits, tokens should not be drained +further when they reach 0, but such things may happen. + +An `rlimit`can be asked how long to wait until `tokens` are positive again. +This is given in milliseconds. When token are available, this wait +time is 0. + +Ideally a user of `rlimit` would consume the available tokens to 0, then +get a wait times of 1000ms, after which the set rate of tokens has +regenerated. Rinse and repeat. + +Should a user drain twice the amount of the rate, tokens are negative +and the wait time is 2 seconds. The `spare_us` account for the +time that has passed for the consumption. When a user takes 250ms to +consume the rate, the wait time is then 750ms. + +When a user drains nothing for two seconds, the available tokens would +grow to twice the rate, unless a burst rate is set. + +Finally, an `rlimit` may be set to `blocked` and later unblocked again. +A blocked `rlimit` has no tokens available. This works also when the rate +is unlimited (`rate_per_sec` set to 0). + +### Downloads + +`rlimit` is in `data->progress.dl.rlimit`. `setopt.c` initializes it whenever +the application sets `CURLOPT_MAX_RECV_SPEED_LARGE`. This may be done +in the middle of a transfer. + +`rlimit` tokens are drained in the "protocol" client writer. Checks for +capacity depend on the protocol: + +* HTTP and other plain protocols: `transfer.c:sendrecv_dl()` reads only +up to capacity. +* HTTP/2: capacity is used to adjust a stream's window size. Since all +streams start with `64kb`, `rlimit` takes a few seconds to take effect. +* HTTP/3: ngtcp2 acknowledges stream data according to capacity. It +keeps track of bytes not acknowledged yet. This has the same effect as HTTP/2 +window sizes. + +(The quiche API does not offer control of `ACK`s and `rlimits` for download +do not work in that backend.) + +### Uploads + +`rlimit` is in `data->progress.ul.rlimit`. `setopt.c` initializes it whenever +the application sets `CURLOPT_MAX_SEND_SPEED_LARGE`. This may be done +in the middle of a transfer. + +The upload capacity is checked in `Curl_client_read()` and readers are +only asked to read bytes up to the `rlimit` capacity. This limits upload +of data for all protocols in the same way. + +### Pause/Unpause + +Pausing of up-/downloads sets the corresponding `rlimit` to blocked. Unpausing +removes that block. + +### Suspending transfers + +While obeying the `rlimit` for up-/download leads to the desired transfer +rates, the other issue that needs care is CPU consumption. + +`rlimits` are inspected when computing the "pollset" of a transfer. When +a transfer wants to send, but not send tokens are available, the `POLLOUT` +is removed from the pollset. Same for receiving. + +For a transfer that is, due to `rlimit`, not able to progress, the pollset +is then empty. No socket events are monitored, no CPU activity +happens. For paused transfers, this is sufficient. + +Draining `rlimit` happens when a transfer is in `PERFORM` state and +exhausted limits cause the timer `TOOFAST` to be set. When the fires, +the transfer runs again and `rlimit`s are re-evaluated. diff --git a/docs/internals/SCORECARD.md b/docs/internals/SCORECARD.md index 546959760417..145267f8c3a6 100644 --- a/docs/internals/SCORECARD.md +++ b/docs/internals/SCORECARD.md @@ -12,14 +12,14 @@ curl/libcurl in a reproducible fashion to judge improvements or detect regressions. They are not intended to represent real world scenarios as such. -This script is not part of any official interface and we may -change it in the future according to the project's needs. +This script is not part of any official interface and we may change it in +the future according to the project's needs. ## setup -When you are able to run curl's `pytest` suite, scorecard should work -for you as well. They start a local Apache httpd or Caddy server and -invoke the locally build `src/curl` (by default). +When you are able to run curl's `pytest` suite, scorecard should work for you +as well. They start a local Apache httpd or Caddy server and invoke the +locally build `src/curl` (by default). ## invocation @@ -29,8 +29,9 @@ A typical invocation for measuring performance of HTTP/2 downloads would be: curl> python3 tests/http/scorecard.py -d h2 ``` -and this prints a table with the results. The last argument is the protocol to test and -it can be `h1`, `h2` or `h3`. You can add `--json` to get results in JSON instead of text. +and this prints a table with the results. The last argument is the protocol to +test and it can be `h1`, `h2` or `h3`. You can add `--json` to get results in +JSON instead of text. Help for all command line options are available via: @@ -40,11 +41,12 @@ curl> python3 tests/http/scorecard.py -h ## scenarios -Apart from `-d/--downloads` there is `-u/--uploads` and `-r/--requests`. These are run with -a variation of resource sizes and parallelism by default. You can specify these in some way -if you are just interested in a particular case. +Apart from `-d/--downloads` there is `-u/--uploads` and `-r/--requests`. These +are run with a variation of resource sizes and parallelism by default. You can +specify these in some way if you are just interested in a particular case. -For example, to run downloads of a 1 MB resource only, 100 times with at max 6 parallel transfers, use: +For example, to run downloads of a 1 MB resource only, 100 times with at max 6 +parallel transfers, use: ``` curl> python3 tests/http/scorecard.py -d --download-sizes=1mb --download-count=100 --download-parallel=6 h2 @@ -61,21 +63,28 @@ involved. (Note: this does not work for HTTP/3) ## flame graphs -With the excellent [Flame Graph](https://github.com/brendangregg/FlameGraph) by Brendan Gregg, scorecard can turn `perf`/`dtrace` samples into an interactive SVG. Either clone the `Flamegraph` repository next to your `curl` project or set the environment variable `FLAMEGRAPH` to the location of your clone. Then run scorecard with the `--flame` option, like +With the excellent [Flame Graph](https://github.com/brendangregg/FlameGraph) +by Brendan Gregg, scorecard can turn `perf`/`dtrace` samples into an +interactive SVG. Either clone the `Flamegraph` repository next to your `curl` +project or set the environment variable `FLAMEGRAPH` to the location of your +clone. Then run scorecard with the `--flame` option, like ``` curl> FLAMEGRAPH=/Users/sei/projects/FlameGraph python3 tests/http/scorecard.py \ -r --request-count=50000 --request-parallels=100 --samples=1 --flame h2 ``` -and the SVG of the run is in `tests/http/gen/curl/curl.flamegraph.svg`. You can open that in Firefox and zoom in/out of stacks of interest. -The flame graph is about the last run of `curl`. That is why you should add scorecard arguments -that restrict measurements to a single run. +and the SVG of the run is in `tests/http/gen/curl/curl.flamegraph.svg`. You +can open that in Firefox and zoom in/out of stacks of interest. + +The flame graph is about the last run of `curl`. That is why you should add +scorecard arguments that restrict measurements to a single run. ### Measures/Privileges -The `--flame` option uses `perf` on linux and `dtrace` on macOS. Since both tools require special -privileges, they are run via the `sudo` command by scorecard. This means you need to issue a -`sudo` recently enough before running scorecard, so no new password check is needed. +The `--flame` option uses `perf` on linux and `dtrace` on macOS. Since both +tools require special privileges, they are run via the `sudo` command by +scorecard. This means you need to issue a `sudo` recently enough before +running scorecard, so no new password check is needed. There is no support right now for measurements on other platforms. diff --git a/docs/internals/TIME-KEEPING.md b/docs/internals/TIME-KEEPING.md new file mode 100644 index 000000000000..91ac4d9cadc9 --- /dev/null +++ b/docs/internals/TIME-KEEPING.md @@ -0,0 +1,53 @@ + + +# Keeping Time + +Transfers need the current time to handle timeouts and keep a record of +events. The current time function is `curlx_now()` and it uses a **monotonic** +clock on most platforms. This ensures that time only ever increases (the +timestamps it gives are however not the "real" world clock). + +## Initial Approach (now historic) + +The loop processing functions called `curlx_now()` at the beginning and then +passed a pointer to the `struct curltime now` to functions to save them the +calls. Passing this pointer down to all functions possibly involved was not +done as this pollutes the internal APIs. + +So, some functions continued to call `curlx_now()` on their own while others +used the passed pointer *to a timestamp in the past*. This led to a transfer +experiencing *jumps* in time, reversing cause and effect. On fast systems, +this was mostly not noticeable. On slow machines or in CI, this led to rare +and annoying test failures. + +(Especially when we added assertions that the reported "timeline" of a +transfer was in the correct order: *queue -> nameloopup -> connect -> +appconnect ->...*.) + +## Revised Approach + +The strategy of handling transfer's time is now: + +* Keep a "now" timestamp in the multi handle. Keep a fallback "now" timestamp + in the easy handle. +* Always use `Curl_pgrs_now(data)` to get the current time of a transfer. +* Do not use `curlx_now()` directly for transfer handling (exceptions apply + for loops). + +This has the following advantages: + +* No need to pass a `struct curltime` around or pass a pointer to an outdated + timestamp to other functions. +* No need to calculate the exact `now` until it is really used. +* Passing a `const` pointer is better than struct passing. Updating and + passing a pointer to the same memory location for all transfers is even + better. + +Caveats: + +* do not store the pointer returned by `Curl_pgrs_now(data)` anywhere that + outlives the current code invocation. diff --git a/docs/internals/TLS-SESSIONS.md b/docs/internals/TLS-SESSIONS.md index 8f887d2e071d..add735bb03bd 100644 --- a/docs/internals/TLS-SESSIONS.md +++ b/docs/internals/TLS-SESSIONS.md @@ -68,7 +68,6 @@ peer keys for this reason. a previous ticket, curl might trust a server which no longer has a root certificate in the file. - ## Session Cache Access #### Lookups diff --git a/docs/internals/UINT_SETS.md b/docs/internals/UINT_SETS.md index de00b9b47a30..963cc82d48fe 100644 --- a/docs/internals/UINT_SETS.md +++ b/docs/internals/UINT_SETS.md @@ -4,35 +4,34 @@ Copyright (C) Daniel Stenberg, , et al. SPDX-License-Identifier: curl --> -# Unsigned Int Sets +# `uint32_t` Sets -The multi handle tracks added easy handles via an unsigned int -it calls an `mid`. There are four data structures for unsigned int -optimized for the multi use case. +The multi handle tracks added easy handles via an `uint32_t` it calls an +`mid`. There are four data structures for `uint32_t` optimized for the multi +use case. -## `uint_tbl` +## `uint32_tbl` -`uint_table`, implemented in `uint-table.[ch]` manages an array -of `void *`. The unsigned int are the index into this array. It is -created with a *capacity* which can be *resized*. The table assigns -the index when a `void *` is *added*. It keeps track of the last -assigned index and uses the next available larger index for a -subsequent add. Reaching *capacity* it wraps around. +`uint32_table`, implemented in `uint-table.[ch]` manages an array of `void *`. +The `uint32_t` is the index into this array. It is created with a *capacity* +which can be *resized*. The table assigns the index when a `void *` is +*added*. It keeps track of the last assigned index and uses the next available +larger index for a subsequent add. Reaching *capacity* it wraps around. The table *can not* store `NULL` values. The largest possible index -is `UINT_MAX - 1`. +is `UINT32_MAX - 1`. -The table is iterated over by asking for the *first* existing index, -meaning the smallest number that has an entry, if the table is not -empty. To get the *next* entry, one passes the index of the previous -iteration step. It does not matter if the previous index is still -in the table. Sample code for a table iteration would look like this: +The table is iterated over by asking for the *first* existing index, meaning +the smallest number that has an entry, if the table is not empty. To get +the *next* entry, one passes the index of the previous iteration step. It does +not matter if the previous index is still in the table. Sample code for a table +iteration would look like this: ```c -unsigned int mid; +uint32_t int mid; void *entry; -if(Curl_uint_tbl_first(tbl, &mid, &entry)) { +if(Curl_uint32_tbl_first(tbl, &mid, &entry)) { do { /* operate on entry with index mid */ } @@ -45,51 +44,56 @@ This iteration has the following properties: * entries in the table can be added/removed safely. * all entries that are not removed during the iteration are visited. -* the table may be resized to a larger capacity without affecting visited entries. +* the table may be resized to a larger capacity without affecting visited + entries. * entries added with a larger index than the current are visited. ### Memory -For storing 1000 entries, the table would allocate one block of 8KB on a 64-bit system, -plus the 2 pointers and 3 unsigned int in its base `struct uint_tbl`. A resize -allocates a completely new pointer array, copy the existing entries and free the previous one. +For storing 1000 entries, the table would allocate one block of 8KB on +a 64-bit system, plus the 2 pointers and 3 `uint32_t` in its base `struct +uint32_tbl`. A resize allocates a completely new pointer array, copy +the existing entries and free the previous one. ### Performance -Lookups of entries are only an index into the array, O(1) with a tiny 1. Adding -entries and iterations are more work: +Lookups of entries are only an index into the array, O(1) with a tiny 1. +Adding entries and iterations are more work: -1. adding an entry means "find the first free index larger than the previous assigned - one". Worst case for this is a table with only a single free index where `capacity - 1` - checks on `NULL` values would be performed, O(N). If the single free index is randomly - distributed, this would be O(N/2). -2. iterating a table scans for the first not `NULL` entry after the start index. This - makes a complete iteration O(N) work. +1. adding an entry means "find the first free index larger than the previous + assigned one". Worst case for this is a table with only a single free index + where `capacity - 1` checks on `NULL` values would be performed, O(N). If + the single free index is randomly distributed, this would be O(N/2). +2. iterating a table scans for the first not `NULL` entry after the start + index. This makes a complete iteration O(N) work. -In the multi use case, point 1 is remedied by growing the table so that a good chunk -of free entries always exists. +In the multi use case, point 1 is remedied by growing the table so that a good +chunk of free entries always exists. -Point 2 is less of an issue for a multi, since it does not really matter when the -number of transfer is relatively small. A multi managing a larger set needs to operate -event based anyway and table iterations rarely are needed. +Point 2 is less of an issue for a multi, since it does not really matter when +the number of transfer is relatively small. A multi managing a larger set +needs to operate event based anyway and table iterations rarely are needed. For these reasons, the simple implementation was preferred. Should this become -a concern, there are options like "free index lists" or, alternatively, an internal -bitset that scans better. +a concern, there are options like "free index lists" or, alternatively, an +internal bitset that scans better. -## `uint_bset` +## `uint32_bset` -A bitset for unsigned integers, allowing fast add/remove operations. It is initialized -with a *capacity*, meaning it can store only the numbers in the range `[0, capacity-1]`. -It can be *resized* and safely *iterated*. `uint_bset` is designed to operate in combination with `uint_tbl`. +A bitset for `uint32_t` values, allowing fast add/remove operations. It is +initialized with a *capacity*, meaning it can store only the numbers in the +range `[0, capacity-1]`. It can be *resized* and safely *iterated*. +`uint32_bset` is designed to operate in combination with `uint_tbl`. -The bitset keeps an array of `curl_uint64_t`. The first array entry keeps the numbers 0 to 63, the -second 64 to 127 and so on. A bitset with capacity 1024 would therefore allocate an array -of 16 64-bit values (128 bytes). Operations for an unsigned int divide it by 64 for the array index and then check/set/clear the bit of the remainder. +The bitset keeps an array of `uint64_t`. The first array entry keeps the +numbers 0 to 63, the second 64 to 127 and so on. A bitset with capacity 1024 +would therefore allocate an array of 16 64-bit values (128 bytes). Operations +for an unsigned int divide it by 64 for the array index and then +check/set/clear the bit of the remainder. -Iterator works the same as with `uint_tbl`: ask the bitset for the *first* number present and -then use that to get the *next* higher number present. Like the table, this safe for -adds/removes and growing the set while iterating. +Iterator works the same as with `uint32_tbl`: ask the bitset for the *first* +number present and then use that to get the *next* higher number present. Like +the table, this safe for adds/removes and growing the set while iterating. ### Memory @@ -98,31 +102,36 @@ A bitset for 40000 transfers occupies 5KB of memory. ## Performance -Operations for add/remove/check are O(1). Iteration needs to scan for the next bit set. The -number of scans is small (see memory footprint) and, for checking bits, many compilers -offer primitives for special CPU instructions. +Operations for add/remove/check are O(1). Iteration needs to scan for the next +bit set. The number of scans is small (see memory footprint) and, for checking +bits, many compilers offer primitives for special CPU instructions. -## `uint_spbset` +## `uint32_spbset` -While the memory footprint of `uint_bset` is good, it still needs 5KB to store the single number 40000. This -is not optimal when many are needed. For example, in event based processing, each socket needs to -keep track of the transfers involved. There are many sockets potentially, but each one mostly tracks -a single transfer or few (on HTTP/2 connection borderline up to 100). +While the memory footprint of `uint32_bset` is good, it still needs 5KB to +store the single number 40000. This is not optimal when many are needed. For +example, in event based processing, each socket needs to keep track of the +transfers involved. There are many sockets potentially, but each one mostly +tracks a single transfer or few (on HTTP/2 connection borderline up to 100). -For such uses cases, the `uint_spbset` is intended: track a small number of unsigned int, potentially -rather "close" together. It keeps "chunks" with an offset and has no capacity limit. +For such uses cases, the `uint32_spbset` is intended: track a small number of +unsigned int, potentially rather "close" together. It keeps "chunks" with an +offset and has no capacity limit. -Example: adding the number 40000 to an empty sparse bitset would have one chunk with offset 39936, keeping -track of the numbers 39936 to 40192 (a chunk has 4 64-bit values). The numbers in that range can be handled -without further allocations. +Example: adding the number 40000 to an empty sparse bitset would have one +chunk with offset 39936, keeping track of the numbers 39936 to 40192 (a chunk +has 4 64-bit values). The numbers in that range can be handled without further +allocations. -The worst case is then storing 100 numbers that lie in separate intervals. Then 100 chunks -would need to be allocated and linked, resulting in overall 4 KB of memory used. +The worst case is then storing 100 numbers that lie in separate intervals. +Then 100 chunks would need to be allocated and linked, resulting in overall 4 +KB of memory used. Iterating a sparse bitset works the same as for bitset and table. -## `uint_hash` +## `uint32_hash` -At last, there are places in libcurl such as the HTTP/2 and HTTP/3 protocol implementations that need -to store their own data related to a transfer. `uint_hash` allows then to associate an unsigned int, -e.g. the transfer's `mid`, to their own data. +At last, there are places in libcurl such as the HTTP/2 and HTTP/3 protocol +implementations that need to store their own data related to a transfer. +`uint32_hash` allows then to associate an unsigned int, e.g. the transfer's +`mid`, to their own data. diff --git a/docs/libcurl/curl_easy_cleanup.md b/docs/libcurl/curl_easy_cleanup.md index fc653e3a56d7..ee722ca84d9c 100644 --- a/docs/libcurl/curl_easy_cleanup.md +++ b/docs/libcurl/curl_easy_cleanup.md @@ -62,11 +62,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); - res = curl_easy_perform(curl); - if(res) - printf("error: %s\n", curl_easy_strerror(res)); + result = curl_easy_perform(curl); + if(result) + printf("error: %s\n", curl_easy_strerror(result)); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/curl_easy_duphandle.md b/docs/libcurl/curl_easy_duphandle.md index 45e738f301bf..5ea9c4fba018 100644 --- a/docs/libcurl/curl_easy_duphandle.md +++ b/docs/libcurl/curl_easy_duphandle.md @@ -56,11 +56,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; CURL *nother; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); nother = curl_easy_duphandle(curl); - res = curl_easy_perform(nother); + result = curl_easy_perform(nother); curl_easy_cleanup(nother); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/curl_easy_escape.md b/docs/libcurl/curl_easy_escape.md index b10500ac2619..1480a75c591a 100644 --- a/docs/libcurl/curl_easy_escape.md +++ b/docs/libcurl/curl_easy_escape.md @@ -30,7 +30,8 @@ char *curl_easy_escape(CURL *curl, const char *string, int length); 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). +(**%NN** where **NN** is a two-digit hexadecimal number). Although not +constrained by its type, the returned string may not be altered. 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 diff --git a/docs/libcurl/curl_easy_getinfo.md b/docs/libcurl/curl_easy_getinfo.md index 9515fadeed2c..a7665f46ad60 100644 --- a/docs/libcurl/curl_easy_getinfo.md +++ b/docs/libcurl/curl_easy_getinfo.md @@ -398,7 +398,6 @@ An overview of the time values available from curl_easy_getinfo(3) |--|--|--|--|--|--|--|--TOTAL |--|--|--|--|--|--|--|--REDIRECT - CURLINFO_QUEUE_TIME_T(3), CURLINFO_NAMELOOKUP_TIME_T(3), CURLINFO_CONNECT_TIME_T(3), CURLINFO_APPCONNECT_TIME_T(3), CURLINFO_PRETRANSFER_TIME_T(3), CURLINFO_POSTTRANSFER_TIME_T(3), @@ -414,16 +413,16 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(CURLE_OK == res) { + if(CURLE_OK == result) { char *ct; /* ask for the content-type */ - res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct); + result = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct); - if((CURLE_OK == res) && ct) + if((CURLE_OK == result) && ct) printf("We received Content-Type: %s\n", ct); } diff --git a/docs/libcurl/curl_easy_init.md b/docs/libcurl/curl_easy_init.md index 909f3c7ac75a..34dbc640b9f1 100644 --- a/docs/libcurl/curl_easy_init.md +++ b/docs/libcurl/curl_easy_init.md @@ -60,9 +60,9 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/curl_easy_nextheader.md b/docs/libcurl/curl_easy_nextheader.md index 2dbdf61ccdbd..c3dd223b8c8c 100644 --- a/docs/libcurl/curl_easy_nextheader.md +++ b/docs/libcurl/curl_easy_nextheader.md @@ -83,7 +83,7 @@ int main(void) } /* extract the normal headers + 1xx + trailers from the last request */ - unsigned int origin = CURLH_HEADER| CURLH_1XX | CURLH_TRAILER; + 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; diff --git a/docs/libcurl/curl_easy_pause.md b/docs/libcurl/curl_easy_pause.md index 2f47c4ef3f7f..b6390058e89a 100644 --- a/docs/libcurl/curl_easy_pause.md +++ b/docs/libcurl/curl_easy_pause.md @@ -109,7 +109,6 @@ int main(void) if(curl) { /* pause a transfer in both directions */ curl_easy_pause(curl, CURLPAUSE_RECV | CURLPAUSE_SEND); - } } ~~~ diff --git a/docs/libcurl/curl_easy_perform.md b/docs/libcurl/curl_easy_perform.md index 3d19669a5313..cc61232f875c 100644 --- a/docs/libcurl/curl_easy_perform.md +++ b/docs/libcurl/curl_easy_perform.md @@ -68,9 +68,9 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/curl_easy_recv.md b/docs/libcurl/curl_easy_recv.md index e89c03592bf8..aeb16c0ce535 100644 --- a/docs/libcurl/curl_easy_recv.md +++ b/docs/libcurl/curl_easy_recv.md @@ -67,22 +67,22 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); - if(res == CURLE_OK) { + if(result == CURLE_OK) { char buf[256]; size_t nread; curl_socket_t sockfd; /* Extract the socket from the curl handle - we need it for waiting. */ - res = curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sockfd); + result = curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sockfd); /* read data */ - res = curl_easy_recv(curl, buf, sizeof(buf), &nread); + result = curl_easy_recv(curl, buf, sizeof(buf), &nread); } } } diff --git a/docs/libcurl/curl_easy_send.md b/docs/libcurl/curl_easy_send.md index 885b37f1bcf6..016a6756a848 100644 --- a/docs/libcurl/curl_easy_send.md +++ b/docs/libcurl/curl_easy_send.md @@ -62,20 +62,20 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); - if(res == CURLE_OK) { + if(result == CURLE_OK) { curl_socket_t sockfd; size_t sent; /* Extract the socket from the curl handle - we need it for waiting. */ - res = curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sockfd); + result = curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sockfd); /* send data */ - res = curl_easy_send(curl, "hello", 5, &sent); + result = curl_easy_send(curl, "hello", 5, &sent); } } } diff --git a/docs/libcurl/curl_easy_setopt.md b/docs/libcurl/curl_easy_setopt.md index 430c3c14abbc..771442b18504 100644 --- a/docs/libcurl/curl_easy_setopt.md +++ b/docs/libcurl/curl_easy_setopt.md @@ -686,6 +686,10 @@ Port number to connect to. See CURLOPT_PORT(3) Make an HTTP POST. See CURLOPT_POST(3) +## CURLOPT_POSTFIELDS + +Send a POST with this data - does not copy it. See CURLOPT_POSTFIELDS(3) + ## CURLOPT_POSTFIELDSIZE The POST data is this big. See CURLOPT_POSTFIELDSIZE(3) @@ -1352,9 +1356,9 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/curl_easy_ssls_export.md b/docs/libcurl/curl_easy_ssls_export.md index 32f2fff240b1..b4960be1d148 100644 --- a/docs/libcurl/curl_easy_ssls_export.md +++ b/docs/libcurl/curl_easy_ssls_export.md @@ -139,7 +139,7 @@ int main(void) { CURLSHcode sh; CURLSH *share = curl_share_init(); - CURLcode rc; + CURLcode result; CURL *curl; sh = curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION); @@ -156,7 +156,7 @@ int main(void) curl_easy_perform(curl); /* export the TLS sessions collected in the share */ - rc = curl_easy_ssls_export(curl, my_export_cb, NULL); + result = curl_easy_ssls_export(curl, my_export_cb, NULL); /* always cleanup */ curl_easy_cleanup(curl); diff --git a/docs/libcurl/curl_easy_ssls_import.md b/docs/libcurl/curl_easy_ssls_import.md index f512c2fe694c..178c10654c73 100644 --- a/docs/libcurl/curl_easy_ssls_import.md +++ b/docs/libcurl/curl_easy_ssls_import.md @@ -53,7 +53,7 @@ int main(void) { CURLSHcode sh; CURLSH *share = curl_share_init(); - CURLcode rc; + CURLcode result; CURL *curl; sh = curl_share_setopt(share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION); @@ -68,7 +68,7 @@ int main(void) curl_easy_setopt(curl, CURLOPT_SHARE, share); /* read shmac and sdata from storage */ - rc = curl_easy_ssls_import(curl, NULL, shmac, hlen, sdata, slen); + result = curl_easy_ssls_import(curl, NULL, shmac, hlen, sdata, slen); /* always cleanup */ curl_easy_cleanup(curl); diff --git a/docs/libcurl/curl_easy_strerror.md b/docs/libcurl/curl_easy_strerror.md index 37040a1c1e7a..bec2bdc1a32c 100644 --- a/docs/libcurl/curl_easy_strerror.md +++ b/docs/libcurl/curl_easy_strerror.md @@ -43,14 +43,14 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; /* set options */ /* Perform the entire transfer */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); } } ~~~ diff --git a/docs/libcurl/curl_easy_unescape.md b/docs/libcurl/curl_easy_unescape.md index 2e78ad5d9f07..49e4c6bf269a 100644 --- a/docs/libcurl/curl_easy_unescape.md +++ b/docs/libcurl/curl_easy_unescape.md @@ -30,7 +30,8 @@ char *curl_easy_unescape(CURL *curl, const char *input, 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. +binary versions. Although not constrained by its type, the returned data may +not be altered. If the **length** argument is set to 0 (zero), curl_easy_unescape(3) uses strlen() on **input** to find out the size. diff --git a/docs/libcurl/curl_escape.md b/docs/libcurl/curl_escape.md index c24d1890d493..967d375a9758 100644 --- a/docs/libcurl/curl_escape.md +++ b/docs/libcurl/curl_escape.md @@ -31,7 +31,8 @@ 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). +**NN** is a two-digit hexadecimal number). Although not constrained by its +type, the returned string may not be altered. If the **length** argument is set to 0, curl_escape(3) uses strlen() on **string** to find out the size. diff --git a/docs/libcurl/curl_formadd.md b/docs/libcurl/curl_formadd.md index f35e50eab754..ca05f4310aff 100644 --- a/docs/libcurl/curl_formadd.md +++ b/docs/libcurl/curl_formadd.md @@ -225,7 +225,7 @@ int main(void) 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 */ diff --git a/docs/libcurl/curl_formget.md b/docs/libcurl/curl_formget.md index 264eb5cbcbb3..316609e93a97 100644 --- a/docs/libcurl/curl_formget.md +++ b/docs/libcurl/curl_formget.md @@ -54,7 +54,7 @@ This, because first then does libcurl known which actual read callback to use. size_t print_httppost_callback(void *arg, const char *buf, size_t len) { fwrite(buf, len, 1, stdout); - (*(size_t *) arg) += len; + (*(size_t *)arg) += len; return len; } @@ -62,7 +62,7 @@ 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 (size_t)-1; } return total_size; } diff --git a/docs/libcurl/curl_getenv.md b/docs/libcurl/curl_getenv.md index 2cfb58148ce7..047c913f2530 100644 --- a/docs/libcurl/curl_getenv.md +++ b/docs/libcurl/curl_getenv.md @@ -29,7 +29,8 @@ 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 Windows). -You must curl_free(3) the returned string when you are done with it. +You must curl_free(3) the returned string when you are done with it and, +although not constrained by its type, it may not be altered. # %PROTOCOLS% diff --git a/docs/libcurl/curl_global_cleanup.md b/docs/libcurl/curl_global_cleanup.md index 60a761ed5c50..1c3dac9aa35f 100644 --- a/docs/libcurl/curl_global_cleanup.md +++ b/docs/libcurl/curl_global_cleanup.md @@ -40,7 +40,7 @@ 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 +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 diff --git a/docs/libcurl/curl_global_init.md b/docs/libcurl/curl_global_init.md index 724f90cddc8f..093a530351ec 100644 --- a/docs/libcurl/curl_global_init.md +++ b/docs/libcurl/curl_global_init.md @@ -52,7 +52,7 @@ If this is not thread-safe (the bit mentioned above is not set), 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 +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 diff --git a/docs/libcurl/curl_global_trace.md b/docs/libcurl/curl_global_trace.md index 0459eab6747d..fa08df7c72ef 100644 --- a/docs/libcurl/curl_global_trace.md +++ b/docs/libcurl/curl_global_trace.md @@ -43,7 +43,7 @@ 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 +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 @@ -130,6 +130,10 @@ states. Traces reading of upload data from the application in order to send it to the server. +## `ssh` + +Tracing of SSH related protocols SCP and SFTP. + ## `ssls` Tracing of SSL Session handling, e.g. caching/import/export. diff --git a/docs/libcurl/curl_mime_data_cb.md b/docs/libcurl/curl_mime_data_cb.md index 9b3fdd5593bd..bed7c5d78f47 100644 --- a/docs/libcurl/curl_mime_data_cb.md +++ b/docs/libcurl/curl_mime_data_cb.md @@ -120,7 +120,7 @@ struct ctl { size_t read_callback(char *buffer, size_t size, size_t nitems, void *arg) { - struct ctl *p = (struct ctl *) arg; + struct ctl *p = (struct ctl *)arg; curl_off_t sz = p->size - p->position; nitems *= size; diff --git a/docs/libcurl/curl_mprintf.md b/docs/libcurl/curl_mprintf.md index 4f5c090579ba..508dece91974 100644 --- a/docs/libcurl/curl_mprintf.md +++ b/docs/libcurl/curl_mprintf.md @@ -67,7 +67,7 @@ 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. +may not be overwritten and 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. @@ -274,7 +274,7 @@ 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); + curl_mprintf("Pi is almost %f\n", (double)25.0 / 8); } ~~~ diff --git a/docs/libcurl/curl_multi_assign.md b/docs/libcurl/curl_multi_assign.md index 36579fd9f83b..6ae60fe66704 100644 --- a/docs/libcurl/curl_multi_assign.md +++ b/docs/libcurl/curl_multi_assign.md @@ -60,9 +60,9 @@ int main(void) curl_socket_t fd = 0; /* file descriptor to associate our data with */ /* make our struct pointer associated with socket fd */ - CURLMcode mc = curl_multi_assign(multi, fd, &private); - if(mc) - printf("error: %s\n", curl_multi_strerror(mc)); + CURLMcode mresult = curl_multi_assign(multi, fd, &private); + if(mresult) + printf("error: %s\n", curl_multi_strerror(mresult)); } ~~~ diff --git a/docs/libcurl/curl_multi_fdset.md b/docs/libcurl/curl_multi_fdset.md index 1396738014c3..7ab65e424a0d 100644 --- a/docs/libcurl/curl_multi_fdset.md +++ b/docs/libcurl/curl_multi_fdset.md @@ -91,8 +91,8 @@ int main(void) fd_set fdexcep; int maxfd; int rc; - CURLMcode mc; - struct timeval timeout = {1, 0}; + CURLMcode mresult; + struct timeval timeout = { 1, 0 }; CURLM *multi = curl_multi_init(); @@ -105,17 +105,17 @@ int main(void) FD_ZERO(&fdexcep); /* get file descriptors from the transfers */ - mc = curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd); + mresult = curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd); - if(mc != CURLM_OK) { - fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mc); + if(mresult != CURLM_OK) { + fprintf(stderr, "curl_multi_fdset() failed, code %d.\n", mresult); break; } /* wait for activity on one of the sockets */ rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout); - } while(!mc); + } while(!mresult); } ~~~ diff --git a/docs/libcurl/curl_multi_get_handles.md b/docs/libcurl/curl_multi_get_handles.md index f94436a889ba..56da272b8abf 100644 --- a/docs/libcurl/curl_multi_get_handles.md +++ b/docs/libcurl/curl_multi_get_handles.md @@ -41,7 +41,8 @@ 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. +The returned array may not be overwritten and must be freed with a call to +curl_free(3) after use. # %PROTOCOLS% diff --git a/docs/libcurl/curl_multi_perform.md b/docs/libcurl/curl_multi_perform.md index 9ca13c679347..3856e9fd1912 100644 --- a/docs/libcurl/curl_multi_perform.md +++ b/docs/libcurl/curl_multi_perform.md @@ -74,19 +74,18 @@ int main(void) if(curl) { curl_multi_add_handle(multi, curl); do { - CURLMcode mc = curl_multi_perform(multi, &still_running); + CURLMcode mresult = curl_multi_perform(multi, &still_running); - if(!mc && still_running) + if(!mresult && still_running) /* wait for activity, timeout or "nothing" */ - mc = curl_multi_poll(multi, NULL, 0, 1000, NULL); + mresult = curl_multi_poll(multi, NULL, 0, 1000, NULL); - if(mc) { - fprintf(stderr, "curl_multi_poll() failed, code %d.\n", (int)mc); + if(mresult) { + fprintf(stderr, "curl_multi_poll() failed, code %d.\n", (int)mresult); break; } - /* if there are still transfers, loop */ - } while(still_running); + } while(still_running); /* if there are still transfers, loop */ } } ~~~ diff --git a/docs/libcurl/curl_multi_poll.md b/docs/libcurl/curl_multi_poll.md index 64aeac9d10f2..8c2488feb33c 100644 --- a/docs/libcurl/curl_multi_poll.md +++ b/docs/libcurl/curl_multi_poll.md @@ -108,12 +108,12 @@ int main(void) curl_multi_add_handle(multi_handle, easy_handle); do { - CURLMcode mc; + CURLMcode mresult; int numfds; - mc = curl_multi_perform(multi_handle, &still_running); + mresult = curl_multi_perform(multi_handle, &still_running); - if(mc == CURLM_OK) { + if(mresult == CURLM_OK) { struct curl_waitfd myown; myown.fd = myfd; myown.events = CURL_WAIT_POLLIN; /* wait for input */ @@ -121,7 +121,7 @@ int main(void) /* wait for activity on curl's descriptors or on our own, or timeout */ - mc = curl_multi_poll(multi_handle, &myown, 1, 1000, &numfds); + mresult = curl_multi_poll(multi_handle, &myown, 1, 1000, &numfds); if(myown.revents) { /* did our descriptor receive an event? */ @@ -129,8 +129,8 @@ int main(void) } } - if(mc != CURLM_OK) { - fprintf(stderr, "curl_multi failed, code %d.\n", mc); + if(mresult != CURLM_OK) { + fprintf(stderr, "curl_multi failed, code %d.\n", mresult); break; } diff --git a/docs/libcurl/curl_multi_socket_action.md b/docs/libcurl/curl_multi_socket_action.md index 5d4271a38689..44a06406c3e5 100644 --- a/docs/libcurl/curl_multi_socket_action.md +++ b/docs/libcurl/curl_multi_socket_action.md @@ -111,9 +111,9 @@ int main(void) CURLM *multi = curl_multi_init(); - CURLMcode mc = curl_multi_socket_action(multi, fd, bitmask, &running); - if(mc) - printf("error: %s\n", curl_multi_strerror(mc)); + CURLMcode mresult = curl_multi_socket_action(multi, fd, bitmask, &running); + if(mresult) + printf("error: %s\n", curl_multi_strerror(mresult)); } ~~~ diff --git a/docs/libcurl/curl_multi_strerror.md b/docs/libcurl/curl_multi_strerror.md index d419ab2e8222..39b5b2d52426 100644 --- a/docs/libcurl/curl_multi_strerror.md +++ b/docs/libcurl/curl_multi_strerror.md @@ -41,9 +41,9 @@ 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)); + CURLMcode mresult = curl_multi_perform(multi, &still_running); + if(mresult) + printf("error: %s\n", curl_multi_strerror(mresult)); } ~~~ diff --git a/docs/libcurl/curl_multi_wait.md b/docs/libcurl/curl_multi_wait.md index b8f5a18e6746..f9a7b7b6444f 100644 --- a/docs/libcurl/curl_multi_wait.md +++ b/docs/libcurl/curl_multi_wait.md @@ -97,18 +97,18 @@ int main(void) curl_multi_add_handle(multi, easy); do { - CURLMcode mc; + CURLMcode mresult; int numfds; - mc = curl_multi_perform(multi, &still_running); + mresult = curl_multi_perform(multi, &still_running); - if(mc == CURLM_OK) { + if(mresult == CURLM_OK) { /* wait for activity, timeout or "nothing" */ - mc = curl_multi_wait(multi, NULL, 0, 1000, &numfds); + mresult = curl_multi_wait(multi, NULL, 0, 1000, &numfds); } - if(mc != CURLM_OK) { - fprintf(stderr, "curl_multi failed, code %d.\n", mc); + if(mresult != CURLM_OK) { + fprintf(stderr, "curl_multi failed, code %d.\n", mresult); break; } diff --git a/docs/libcurl/curl_multi_waitfds.md b/docs/libcurl/curl_multi_waitfds.md index 7d828a4d7c05..4d6611aa2662 100644 --- a/docs/libcurl/curl_multi_waitfds.md +++ b/docs/libcurl/curl_multi_waitfds.md @@ -62,7 +62,7 @@ than or equal to the number of descriptors. int main(void) { - CURLMcode mc; + CURLMcode mresult; struct curl_waitfd *ufds; CURLM *multi = curl_multi_init(); @@ -73,10 +73,10 @@ int main(void) /* get the count of file descriptors from the transfers */ unsigned int fd_count = 0; - mc = curl_multi_waitfds(multi, NULL, 0, &fd_count); + mresult = curl_multi_waitfds(multi, NULL, 0, &fd_count); - if(mc != CURLM_OK) { - fprintf(stderr, "curl_multi_waitfds() failed, code %d.\n", mc); + if(mresult != CURLM_OK) { + fprintf(stderr, "curl_multi_waitfds() failed, code %d.\n", mresult); break; } @@ -87,10 +87,10 @@ int main(void) ufds = malloc(fd_count * sizeof(struct curl_waitfd)); /* get wait descriptors from the transfers and put them into array. */ - mc = curl_multi_waitfds(multi, ufds, fd_count, &fd_count); + mresult = curl_multi_waitfds(multi, ufds, fd_count, &fd_count); - if(mc != CURLM_OK) { - fprintf(stderr, "curl_multi_waitfds() failed, code %d.\n", mc); + if(mresult != CURLM_OK) { + fprintf(stderr, "curl_multi_waitfds() failed, code %d.\n", mresult); free(ufds); break; } @@ -98,7 +98,7 @@ int main(void) /* Do polling on descriptors in ufds */ free(ufds); - } while(!mc); + } while(!mresult); } ~~~ diff --git a/docs/libcurl/curl_multi_wakeup.md b/docs/libcurl/curl_multi_wakeup.md index 78597bf88f34..d95f9eb6b874 100644 --- a/docs/libcurl/curl_multi_wakeup.md +++ b/docs/libcurl/curl_multi_wakeup.md @@ -61,14 +61,14 @@ int main(void) /* this is thread 1 */ do { - CURLMcode mc; + CURLMcode mresult; int numfds; - mc = curl_multi_perform(multi, &still_running); + mresult = curl_multi_perform(multi, &still_running); - if(mc == CURLM_OK) { + if(mresult == CURLM_OK) { /* wait for activity, timeout or wakeup */ - mc = curl_multi_poll(multi, NULL, 0, 10000, &numfds); + mresult = curl_multi_poll(multi, NULL, 0, 10000, &numfds); } if(time_to_die()) diff --git a/docs/libcurl/curl_pushheader_byname.md b/docs/libcurl/curl_pushheader_byname.md index d066ea7b85b5..e2968fcd4621 100644 --- a/docs/libcurl/curl_pushheader_byname.md +++ b/docs/libcurl/curl_pushheader_byname.md @@ -33,7 +33,8 @@ 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 +data this function points to is freed when this callback returns and, +although not constrained by its type, may not be altered. If more than one header field use the same name, this returns only the first one. # %PROTOCOLS% diff --git a/docs/libcurl/curl_pushheader_bynum.md b/docs/libcurl/curl_pushheader_bynum.md index 12555c57f0c1..2431ff446bb1 100644 --- a/docs/libcurl/curl_pushheader_bynum.md +++ b/docs/libcurl/curl_pushheader_bynum.md @@ -33,7 +33,8 @@ 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. +"name:value" string that gets freed when this callback returns; although +not constrained by its type, this string may not be altered. # %PROTOCOLS% diff --git a/docs/libcurl/curl_slist_append.md b/docs/libcurl/curl_slist_append.md index b2766f728db0..3ebc19e35418 100644 --- a/docs/libcurl/curl_slist_append.md +++ b/docs/libcurl/curl_slist_append.md @@ -33,8 +33,8 @@ new list. The specified **string** has been appended when this function returns. curl_slist_append(3) copies the string. The **string** argument must be a valid string pointer and cannot be NULL. -The list should be freed again (after usage) with -curl_slist_free_all(3). +The list should be freed (after usage) with curl_slist_free_all(3). +Its nodes and pointed content may not be altered outside this function. # %PROTOCOLS% diff --git a/docs/libcurl/curl_unescape.md b/docs/libcurl/curl_unescape.md index 2600f1436110..453fd53145b9 100644 --- a/docs/libcurl/curl_unescape.md +++ b/docs/libcurl/curl_unescape.md @@ -33,7 +33,8 @@ Deprecated. 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. +their plain text versions. Although not constrained by its type, the returned +data may not be altered. If the **length** argument is set to 0, curl_unescape(3) calls strlen() on **input** to find out the size. diff --git a/docs/libcurl/curl_url.md b/docs/libcurl/curl_url.md index 5872134e139a..8053e630b8af 100644 --- a/docs/libcurl/curl_url.md +++ b/docs/libcurl/curl_url.md @@ -38,6 +38,9 @@ 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. +The object must be destroyed with a call to curl_url_cleanup(3) when no +longer needed. + # %PROTOCOLS% # EXAMPLE diff --git a/docs/libcurl/curl_url_get.md b/docs/libcurl/curl_url_get.md index a9bb0bdc23fb..bed1c02f1747 100644 --- a/docs/libcurl/curl_url_get.md +++ b/docs/libcurl/curl_url_get.md @@ -43,6 +43,7 @@ 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. +Although not constrained by its type, the pointed string may not be altered. # FLAGS diff --git a/docs/libcurl/curl_ws_meta.md b/docs/libcurl/curl_ws_meta.md index e34e5476764a..978520afd8d0 100644 --- a/docs/libcurl/curl_ws_meta.md +++ b/docs/libcurl/curl_ws_meta.md @@ -137,8 +137,7 @@ struct customdata { void *ptr; }; -static size_t writecb(char *buffer, - size_t size, size_t nitems, void *p) +static size_t writecb(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); @@ -158,7 +157,6 @@ int main(void) curl_easy_setopt(curl, CURLOPT_WRITEDATA, &custom); curl_easy_perform(curl); - } return 0; } diff --git a/docs/libcurl/curl_ws_recv.md b/docs/libcurl/curl_ws_recv.md index 8c5cd55a4c37..2669256174eb 100644 --- a/docs/libcurl/curl_ws_recv.md +++ b/docs/libcurl/curl_ws_recv.md @@ -74,7 +74,7 @@ int main(void) { char buffer[256]; size_t offset = 0; - CURLcode res = CURLE_OK; + CURLcode result = CURLE_OK; CURL *curl = curl_easy_init(); curl_easy_setopt(curl, CURLOPT_URL, "wss://example.com/"); @@ -82,30 +82,32 @@ int main(void) /* start HTTPS connection and upgrade to WSS, then return control */ curl_easy_perform(curl); - /* Note: This example neglects fragmented messages. (CURLWS_CONT bit) - A real application must handle them appropriately. */ + /* Note: This example neglects fragmented messages. + (CURLWS_CONT bit) A real application must handle them + appropriately. */ - while(!res) { + while(!result) { size_t recv; const struct curl_ws_frame *meta; - res = curl_ws_recv(curl, buffer + offset, sizeof(buffer) - offset, &recv, - &meta); + result = curl_ws_recv(curl, buffer + offset, + sizeof(buffer) - offset, &recv, + &meta); offset += recv; - if(res == CURLE_OK) { + if(result == CURLE_OK) { if(meta->bytesleft == 0) break; /* finished receiving */ if(meta->bytesleft > sizeof(buffer) - offset) - res = CURLE_TOO_LARGE; + result = CURLE_TOO_LARGE; } - if(res == CURLE_AGAIN) + if(result == CURLE_AGAIN) /* in real application: wait for socket here, e.g. using select() */ - res = CURLE_OK; + result = CURLE_OK; } curl_easy_cleanup(curl); - return (int)res; + return (int)result; } ~~~ diff --git a/docs/libcurl/curl_ws_send.md b/docs/libcurl/curl_ws_send.md index ac8f02032126..dc6e927ca848 100644 --- a/docs/libcurl/curl_ws_send.md +++ b/docs/libcurl/curl_ws_send.md @@ -88,7 +88,7 @@ int main(void) { const char *buffer = "PAYLOAD"; size_t offset = 0; - CURLcode res = CURLE_OK; + CURLcode result = CURLE_OK; CURL *curl = curl_easy_init(); curl_easy_setopt(curl, CURLOPT_URL, "wss://example.com/"); @@ -96,24 +96,25 @@ int main(void) /* start HTTPS connection and upgrade to WSS, then return control */ curl_easy_perform(curl); - while(!res) { + while(!result) { size_t sent; - res = curl_ws_send(curl, buffer + offset, strlen(buffer) - offset, &sent, - 0, CURLWS_TEXT); + result = curl_ws_send(curl, buffer + offset, + strlen(buffer) - offset, &sent, + 0, CURLWS_TEXT); offset += sent; - if(res == CURLE_OK) { + if(result == CURLE_OK) { if(offset == strlen(buffer)) break; /* finished sending */ } - if(res == CURLE_AGAIN) + if(result == CURLE_AGAIN) /* in real application: wait for socket here, e.g. using select() */ - res = CURLE_OK; + result = CURLE_OK; } curl_easy_cleanup(curl); - return (int)res; + return (int)result; } ~~~ diff --git a/docs/libcurl/curl_ws_start_frame.md b/docs/libcurl/curl_ws_start_frame.md index 166c5cb7e054..84b8065d93c7 100644 --- a/docs/libcurl/curl_ws_start_frame.md +++ b/docs/libcurl/curl_ws_start_frame.md @@ -102,7 +102,7 @@ int main(void) { CURL *easy; struct read_ctx rctx; - CURLcode res; + CURLcode result; easy = curl_easy_init(); if(!easy) @@ -118,12 +118,12 @@ int main(void) curl_easy_setopt(easy, CURLOPT_READDATA, &rctx); curl_easy_setopt(easy, CURLOPT_UPLOAD, 1L); - /* Perform the request, res gets the return code */ - res = curl_easy_perform(easy); + /* Perform the request, result gets the return code */ + result = curl_easy_perform(easy); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(easy); diff --git a/docs/libcurl/libcurl-env-dbg.md b/docs/libcurl/libcurl-env-dbg.md index 3fcc1935d5ee..ce6b480ae305 100644 --- a/docs/libcurl/libcurl-env-dbg.md +++ b/docs/libcurl/libcurl-env-dbg.md @@ -164,8 +164,3 @@ Make a blocking, graceful shutdown of all remaining connections when a multi handle is destroyed. This implicitly triggers for easy handles that are run via easy_perform. The value of the environment variable gives the shutdown timeout in milliseconds. - -## `CURL_H2_STREAM_WIN_MAX` - -Set to a positive 32-bit number to override the HTTP/2 stream window's -default of 10MB. Used in testing to verify correct window update handling. diff --git a/docs/libcurl/libcurl-security.md b/docs/libcurl/libcurl-security.md index 7fbd32974d2c..62dc12e97e35 100644 --- a/docs/libcurl/libcurl-security.md +++ b/docs/libcurl/libcurl-security.md @@ -144,9 +144,10 @@ The CURLOPT_REDIR_PROTOCOLS_STR(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** +libcurl, including servers hidden behind a firewall from the attacker. E.g. +**https://127.0.0.1/** or +**https://intranet.example/delete-stuff.cgi?delete=all** or +**tftp://bootp-server.example/pc-config-data** Applications can mitigate against this by disabling CURLOPT_FOLLOWLOCATION(3) and handling redirects itself, sanitizing URLs @@ -172,11 +173,10 @@ way you did not intend such as injecting new headers. 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. +**https://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 @@ -254,7 +254,7 @@ the request. 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 +**https://mail.example.com/delete-stuff.cgi?delete=all** Applications can mitigate against this by disabling cookies or clearing them between requests. # Dangerous SCP URLs @@ -315,8 +315,8 @@ 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 +consider. curl supports over 27 different URL schemes. `https://` might be +what you expect, `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. diff --git a/docs/libcurl/libcurl-thread.md b/docs/libcurl/libcurl-thread.md index ef7ae9b7d901..2f60390a668d 100644 --- a/docs/libcurl/libcurl-thread.md +++ b/docs/libcurl/libcurl-thread.md @@ -17,7 +17,7 @@ libcurl-thread - libcurl thread safety # Multi-threading with libcurl -libcurl is thread safe but has no internal thread synchronization. You may have +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. @@ -61,6 +61,13 @@ does this cleanup automatically and there is no leak (added in libcurl 8.8.0). Please review the OpenSSL documentation for a full list of circumstances: https://docs.openssl.org/3.0/man3/OPENSSL_init_crypto/#notes +## mbedTLS + +mbedTLS can be used safely in a multi-threaded environment provided that mbedTLS is +compiled with MBEDTLS_THREADING_C enabled. + +https://mbed-tls.readthedocs.io/en/latest/kb/development/thread-safety-and-multi-threading + # Signals Signals are used for timing out name resolves (during DNS lookup) - when built @@ -84,10 +91,10 @@ 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 +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 @@ -110,7 +117,7 @@ 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) +replacements, must be thread-safe. You can use curl_global_init_mem(3) to set your own replacement memory functions. # Non-safe functions diff --git a/docs/libcurl/libcurl-tutorial.md b/docs/libcurl/libcurl-tutorial.md index e515b3b7b067..6cfe354fc1af 100644 --- a/docs/libcurl/libcurl-tutorial.md +++ b/docs/libcurl/libcurl-tutorial.md @@ -194,7 +194,7 @@ 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://example.com/"); + curl_easy_setopt(handle, CURLOPT_URL, "https://example.com/"); ~~~ Let's assume for a while that you want to receive data as the URL identifies a @@ -272,7 +272,7 @@ 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 is thread-safe but there are a few exceptions. Refer to libcurl-thread(3) for more information. # When It does not Work @@ -448,7 +448,7 @@ 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); + curl_easy_setopt(handle, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST | CURLAUTH_BASIC); ~~~ For convenience, you can use the *CURLAUTH_ANY* define (instead of a list with @@ -468,9 +468,9 @@ pages using the \ 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"; + char *data = "name=daniel&project=curl"; curl_easy_setopt(handle, CURLOPT_POSTFIELDS, data); - curl_easy_setopt(handle, CURLOPT_URL, "http://posthere.com/"); + curl_easy_setopt(handle, CURLOPT_URL, "https://posthere.example/"); curl_easy_perform(handle); /* post away! */ ~~~ @@ -487,7 +487,7 @@ 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; + struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Content-Type: text/xml"); /* post binary data */ @@ -574,8 +574,8 @@ 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; + struct curl_httppost *post = NULL; + struct curl_httppost *last = NULL; curl_formadd(&post, &last, CURLFORM_COPYNAME, "name", CURLFORM_COPYCONTENTS, "daniel", CURLFORM_END); @@ -605,7 +605,7 @@ shows how you set headers to one specific part when you add that to the post handle: ~~~c - struct curl_slist *headers=NULL; + struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Content-Type: text/xml"); curl_formadd(&post, &last, @@ -675,7 +675,7 @@ 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_data_cb(part, (curl_off_t)-1, fread, fseek, NULL, stdin); ~~~ curl_mime_name(3) always copies the field name. The special filename "-" is @@ -717,7 +717,7 @@ becomes: ~~~c part = curl_mime_addpart(multipart); curl_mime_name(part, "stream"); - curl_mime_data_cb(part, (curl_off_t) datasize, + 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"); @@ -738,7 +738,7 @@ becomes: ~~~c part = curl_mime_addpart(multipart); curl_mime_name(part, "memfile"); - curl_mime_data(part, databuffer, (curl_off_t) sizeof databuffer); + curl_mime_data(part, databuffer, (curl_off_t)sizeof(databuffer)); curl_mime_filename(part, "memfile.bin"); ~~~ @@ -802,12 +802,12 @@ 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 */ - } - } + static size_t write_data(void *ptr, size_t size, size_t nmemb, + void *ourpointer) + { + /* do what you want with the data */ + } +} ~~~ # Proxies @@ -1046,7 +1046,7 @@ 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 */ +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"); diff --git a/docs/libcurl/libcurl.m4 b/docs/libcurl/libcurl.m4 index 973493f03af5..96248ddc25f4 100644 --- a/docs/libcurl/libcurl.m4 +++ b/docs/libcurl/libcurl.m4 @@ -86,7 +86,7 @@ AC_DEFUN([LIBCURL_CHECK_CONFIG], AS_HELP_STRING([--with-libcurl=PREFIX],[look for the curl library in PREFIX/lib and headers in PREFIX/include]), [_libcurl_with=$withval],[_libcurl_with=ifelse([$1],,[yes],[$1])]) - if test "$_libcurl_with" != "no"; then + if test "x$_libcurl_with" != "xno"; then AC_PROG_AWK @@ -102,7 +102,7 @@ AC_DEFUN([LIBCURL_CHECK_CONFIG], AC_PATH_PROG([_libcurl_config],[curl-config],[],[$PATH]) fi - if test x$_libcurl_config != "x"; then + if test -n "$_libcurl_config"; then AC_CACHE_CHECK([for the version of libcurl], [libcurl_cv_lib_curl_version], [libcurl_cv_lib_curl_version=`$_libcurl_config --version | $AWK '{print $[]2}'`]) @@ -110,11 +110,11 @@ AC_DEFUN([LIBCURL_CHECK_CONFIG], _libcurl_version=`echo $libcurl_cv_lib_curl_version | $_libcurl_version_parse` _libcurl_wanted=`echo ifelse([$2],,[0],[$2]) | $_libcurl_version_parse` - if test $_libcurl_wanted -gt 0; then + if test "$_libcurl_wanted" -gt 0; then AC_CACHE_CHECK([for libcurl >= version $2], [libcurl_cv_lib_version_ok], [ - if test $_libcurl_version -ge $_libcurl_wanted; then + if test "$_libcurl_version" -ge "$_libcurl_wanted"; then libcurl_cv_lib_version_ok=yes else libcurl_cv_lib_version_ok=no @@ -122,11 +122,11 @@ AC_DEFUN([LIBCURL_CHECK_CONFIG], ]) fi - if test $_libcurl_wanted -eq 0 || test x$libcurl_cv_lib_version_ok = xyes; then - if test x"$LIBCURL_CPPFLAGS" = "x"; then + if test "$_libcurl_wanted" -eq 0 || test "$libcurl_cv_lib_version_ok" = "yes"; then + if test -z "$LIBCURL_CPPFLAGS"; then LIBCURL_CPPFLAGS=`$_libcurl_config --cflags` fi - if test x"$LIBCURL" = "x"; then + if test -z "$LIBCURL"; then LIBCURL=`$_libcurl_config --libs` # This is so silly, but Apple actually has a bug in their @@ -143,7 +143,7 @@ AC_DEFUN([LIBCURL_CHECK_CONFIG], _libcurl_features=`$_libcurl_config --feature` # Is it modern enough to have --protocols? (7.12.4) - if test $_libcurl_version -ge 461828; then + if test "$_libcurl_version" -ge 461828; then _libcurl_protocols=`$_libcurl_config --protocols` fi else @@ -153,7 +153,7 @@ AC_DEFUN([LIBCURL_CHECK_CONFIG], unset _libcurl_wanted fi - if test $_libcurl_try_link = yes; then + if test "$_libcurl_try_link" = "yes"; then # we did not find curl-config, so let's see if the user-supplied # link line (or failing that, "-lcurl") is enough. @@ -187,7 +187,7 @@ AC_DEFUN([LIBCURL_CHECK_CONFIG], unset _libcurl_save_libs ]) - if test $libcurl_cv_lib_curl_usable = yes; then + if test "$libcurl_cv_lib_curl_usable" = "yes"; then # Does curl_free() exist in this version of libcurl? # If not, fake it with free() @@ -217,25 +217,25 @@ AC_DEFUN([LIBCURL_CHECK_CONFIG], eval AS_TR_SH(libcurl_feature_$_libcurl_feature)=yes done - if test "x$_libcurl_protocols" = "x"; then + if test -z "$_libcurl_protocols"; then # We do not have --protocols, so just assume that all # protocols are available _libcurl_protocols="HTTP FTP FILE TELNET LDAP DICT TFTP" - if test x$libcurl_feature_SSL = xyes; then + if test "$libcurl_feature_SSL" = "yes"; then _libcurl_protocols="$_libcurl_protocols HTTPS" # FTPS was not standards-compliant until version # 7.11.0 (0x070b00 == 461568) - if test $_libcurl_version -ge 461568; then + if test "$_libcurl_version" -ge 461568; then _libcurl_protocols="$_libcurl_protocols FTPS" fi fi # RTSP, IMAP, POP3 and SMTP were added in # 7.20.0 (0x071400 == 463872) - if test $_libcurl_version -ge 463872; then + if test "$_libcurl_version" -ge 463872; then _libcurl_protocols="$_libcurl_protocols RTSP IMAP POP3 SMTP" fi fi @@ -261,7 +261,7 @@ AC_DEFUN([LIBCURL_CHECK_CONFIG], unset _libcurl_ldflags fi - if test x$_libcurl_with = xno || test x$libcurl_cv_lib_curl_usable != xyes; then + if test "x$_libcurl_with" = "xno" || test "$libcurl_cv_lib_curl_usable" != "yes"; then # This is the IF-NO path ifelse([$4],,:,[$4]) else diff --git a/docs/libcurl/libcurl.md b/docs/libcurl/libcurl.md index b6d4af36e35d..47bf21008704 100644 --- a/docs/libcurl/libcurl.md +++ b/docs/libcurl/libcurl.md @@ -129,7 +129,7 @@ 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 is thread-safe but there are a few exceptions. Refer to libcurl-thread(3) for more information. # PERSISTENT CONNECTIONS @@ -176,7 +176,7 @@ 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 +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 @@ -184,7 +184,7 @@ 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 +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 diff --git a/docs/libcurl/opts/CMakeLists.txt b/docs/libcurl/opts/CMakeLists.txt index c3e2c2cc6b65..f8b5aaa2def7 100644 --- a/docs/libcurl/opts/CMakeLists.txt +++ b/docs/libcurl/opts/CMakeLists.txt @@ -28,6 +28,7 @@ include("${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake") curl_add_manual_pages(man_MANS) add_custom_target(curl-opts-man DEPENDS ${man_MANS}) add_dependencies(curl-man curl-opts-man) + if(NOT CURL_DISABLE_INSTALL) set(_src "") foreach(_file IN LISTS man_MANS) diff --git a/docs/libcurl/opts/CURLINFO_ACTIVESOCKET.md b/docs/libcurl/opts/CURLINFO_ACTIVESOCKET.md index 0bbb52ff146a..9dbf4f857339 100644 --- a/docs/libcurl/opts/CURLINFO_ACTIVESOCKET.md +++ b/docs/libcurl/opts/CURLINFO_ACTIVESOCKET.md @@ -16,7 +16,7 @@ Added-in: 7.45.0 # NAME -CURLINFO_ACTIVESOCKET - get the active socket +CURLINFO_ACTIVESOCKET - active socket # SYNOPSIS @@ -50,22 +50,22 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); - if(res != CURLE_OK) { - printf("Error: %s\n", curl_easy_strerror(res)); + result = curl_easy_perform(curl); + if(result != CURLE_OK) { + printf("Error: %s\n", curl_easy_strerror(result)); curl_easy_cleanup(curl); return 1; } /* Extract the socket from the curl handle */ - res = curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sockfd); - if(!res && sockfd != CURL_SOCKET_BAD) { + result = curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sockfd); + if(!result && sockfd != CURL_SOCKET_BAD) { /* operate on sockfd */ } diff --git a/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME.md b/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME.md index 1c4a9cafb5de..a11c633dddf8 100644 --- a/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME.md +++ b/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME.md @@ -15,7 +15,7 @@ Added-in: 7.19.0 # NAME -CURLINFO_APPCONNECT_TIME - get the time until the SSL/SSH handshake is completed +CURLINFO_APPCONNECT_TIME - time until the SSL/SSH handshake is completed # SYNOPSIS @@ -47,13 +47,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(CURLE_OK == result) { + result = curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME, &connect); + if(CURLE_OK == result) { printf("Time: %.1f", connect); } } diff --git a/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME_T.md b/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME_T.md index ecaa9dce322c..4b57dd83cb8c 100644 --- a/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME_T.md +++ b/docs/libcurl/opts/CURLINFO_APPCONNECT_TIME_T.md @@ -47,13 +47,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(CURLE_OK == result) { + result = curl_easy_getinfo(curl, CURLINFO_APPCONNECT_TIME_T, &connect); + if(CURLE_OK == result) { printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld", connect / 1000000, (long)(connect % 1000000)); } diff --git a/docs/libcurl/opts/CURLINFO_CAINFO.md b/docs/libcurl/opts/CURLINFO_CAINFO.md index 686e7b9d4e10..23502d22966a 100644 --- a/docs/libcurl/opts/CURLINFO_CAINFO.md +++ b/docs/libcurl/opts/CURLINFO_CAINFO.md @@ -17,7 +17,7 @@ Added-in: 7.84.0 # NAME -CURLINFO_CAINFO - get the default built-in CA certificate path +CURLINFO_CAINFO - default built-in CA certificate path # SYNOPSIS diff --git a/docs/libcurl/opts/CURLINFO_CAPATH.md b/docs/libcurl/opts/CURLINFO_CAPATH.md index c441805ca17f..c58930e0e9bc 100644 --- a/docs/libcurl/opts/CURLINFO_CAPATH.md +++ b/docs/libcurl/opts/CURLINFO_CAPATH.md @@ -20,7 +20,7 @@ Added-in: 7.84.0 # NAME -CURLINFO_CAPATH - get the default built-in CA path string +CURLINFO_CAPATH - default built-in CA path string # SYNOPSIS diff --git a/docs/libcurl/opts/CURLINFO_CERTINFO.md b/docs/libcurl/opts/CURLINFO_CERTINFO.md index d1127afb9b38..e24115f98ffc 100644 --- a/docs/libcurl/opts/CURLINFO_CERTINFO.md +++ b/docs/libcurl/opts/CURLINFO_CERTINFO.md @@ -14,13 +14,13 @@ TLS-backend: - OpenSSL - GnuTLS - Schannel - - rustls + - Rustls Added-in: 7.19.1 --- # NAME -CURLINFO_CERTINFO - get the TLS certificate chain +CURLINFO_CERTINFO - TLS certificate chain # SYNOPSIS @@ -60,7 +60,7 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/"); /* connect to any HTTPS site, trusted or not */ @@ -69,14 +69,14 @@ int main(void) curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { int i; struct curl_certinfo *ci; - res = curl_easy_getinfo(curl, CURLINFO_CERTINFO, &ci); + result = curl_easy_getinfo(curl, CURLINFO_CERTINFO, &ci); - if(!res) { + if(!result) { printf("%d certs!\n", ci->num_of_certs); for(i = 0; i < ci->num_of_certs; i++) { diff --git a/docs/libcurl/opts/CURLINFO_CONDITION_UNMET.md b/docs/libcurl/opts/CURLINFO_CONDITION_UNMET.md index 5f13126ad7c4..1705967dfe13 100644 --- a/docs/libcurl/opts/CURLINFO_CONDITION_UNMET.md +++ b/docs/libcurl/opts/CURLINFO_CONDITION_UNMET.md @@ -16,7 +16,7 @@ Added-in: 7.19.4 # NAME -CURLINFO_CONDITION_UNMET - get info on unmet time conditional or 304 HTTP response. +CURLINFO_CONDITION_UNMET - unmet time conditional or 304 HTTP response # SYNOPSIS @@ -46,7 +46,7 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); @@ -57,13 +57,13 @@ int main(void) curl_easy_setopt(curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE); /* Perform the request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { /* check the time condition */ long unmet; - res = curl_easy_getinfo(curl, CURLINFO_CONDITION_UNMET, &unmet); - if(!res) { + result = curl_easy_getinfo(curl, CURLINFO_CONDITION_UNMET, &unmet); + if(!result) { printf("The time condition was %sfulfilled\n", unmet?"NOT":""); } } diff --git a/docs/libcurl/opts/CURLINFO_CONNECT_TIME.md b/docs/libcurl/opts/CURLINFO_CONNECT_TIME.md index c259e9af5bbb..c9caa070ebea 100644 --- a/docs/libcurl/opts/CURLINFO_CONNECT_TIME.md +++ b/docs/libcurl/opts/CURLINFO_CONNECT_TIME.md @@ -15,7 +15,7 @@ Added-in: 7.4.1 # NAME -CURLINFO_CONNECT_TIME - get the time until connect +CURLINFO_CONNECT_TIME - time to connect # SYNOPSIS @@ -43,13 +43,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(CURLE_OK == result) { + result = curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME, &connect); + if(CURLE_OK == result) { printf("Time: %.1f", connect); } } diff --git a/docs/libcurl/opts/CURLINFO_CONNECT_TIME_T.md b/docs/libcurl/opts/CURLINFO_CONNECT_TIME_T.md index 89ae04c33758..2cfeeb82094a 100644 --- a/docs/libcurl/opts/CURLINFO_CONNECT_TIME_T.md +++ b/docs/libcurl/opts/CURLINFO_CONNECT_TIME_T.md @@ -16,7 +16,7 @@ Added-in: 7.61.0 # NAME -CURLINFO_CONNECT_TIME_T - get the time until connect +CURLINFO_CONNECT_TIME_T - time to connect # SYNOPSIS @@ -45,13 +45,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(CURLE_OK == result) { + result = curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME_T, &connect); + if(CURLE_OK == result) { printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld", connect / 1000000, (long)(connect % 1000000)); } diff --git a/docs/libcurl/opts/CURLINFO_CONN_ID.md b/docs/libcurl/opts/CURLINFO_CONN_ID.md index 1239c1e332a8..75e2ccc5eb74 100644 --- a/docs/libcurl/opts/CURLINFO_CONN_ID.md +++ b/docs/libcurl/opts/CURLINFO_CONN_ID.md @@ -15,7 +15,7 @@ Added-in: 8.2.0 # NAME -CURLINFO_CONN_ID - get the ID of the last connection used by the handle +CURLINFO_CONN_ID - ID of the last connection # SYNOPSIS @@ -44,17 +44,17 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); /* Perform the request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { curl_off_t conn_id; - res = curl_easy_getinfo(curl, CURLINFO_CONN_ID, &conn_id); - if(!res) { + result = curl_easy_getinfo(curl, CURLINFO_CONN_ID, &conn_id); + if(!result) { printf("Connection used: %" CURL_FORMAT_CURL_OFF_T "\n", conn_id); } } diff --git a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD.md b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD.md index 46e8e7ba015d..1142617c19f0 100644 --- a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD.md +++ b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD.md @@ -15,7 +15,7 @@ Added-in: 7.6.1 # NAME -CURLINFO_CONTENT_LENGTH_DOWNLOAD - get content-length of download +CURLINFO_CONTENT_LENGTH_DOWNLOAD - content-length of download # SYNOPSIS @@ -44,17 +44,17 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); /* Perform the request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { /* check the size */ double cl; - res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &cl); - if(!res) { + result = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &cl); + if(!result) { printf("Size: %.0f\n", cl); } } diff --git a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.md b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.md index 7279bd6b6d9d..9bc57e040053 100644 --- a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.md +++ b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.md @@ -15,7 +15,7 @@ Added-in: 7.55.0 # NAME -CURLINFO_CONTENT_LENGTH_DOWNLOAD_T - get content-length of download +CURLINFO_CONTENT_LENGTH_DOWNLOAD_T - content-length of download # SYNOPSIS @@ -41,17 +41,18 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); /* Perform the request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { /* check the size */ curl_off_t cl; - res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &cl); - if(!res) { + result = + curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &cl); + if(!result) { printf("Download size: %" CURL_FORMAT_CURL_OFF_T "\n", cl); } } diff --git a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD.md b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD.md index 725b7f9a45b1..546325f1792c 100644 --- a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD.md +++ b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD.md @@ -15,7 +15,7 @@ Added-in: 7.6.1 # NAME -CURLINFO_CONTENT_LENGTH_UPLOAD - get the specified size of the upload +CURLINFO_CONTENT_LENGTH_UPLOAD - specified size of the upload # SYNOPSIS @@ -43,17 +43,17 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); /* Perform the upload */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { /* check the size */ double cl; - res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_UPLOAD, &cl); - if(!res) { + result = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_UPLOAD, &cl); + if(!result) { printf("Size: %.0f\n", cl); } } diff --git a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD_T.md b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD_T.md index 9b37e54d6dd2..6ad40241fe5e 100644 --- a/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD_T.md +++ b/docs/libcurl/opts/CURLINFO_CONTENT_LENGTH_UPLOAD_T.md @@ -15,7 +15,7 @@ Added-in: 7.55.0 # NAME -CURLINFO_CONTENT_LENGTH_UPLOAD_T - get the specified size of the upload +CURLINFO_CONTENT_LENGTH_UPLOAD_T - specified size of the upload # SYNOPSIS @@ -40,17 +40,17 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); /* Perform the upload */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { /* check the size */ curl_off_t cl; - res = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_UPLOAD_T, &cl); - if(!res) { + result = curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_UPLOAD_T, &cl); + if(!result) { printf("Upload size: %" CURL_FORMAT_CURL_OFF_T "\n", cl); } } diff --git a/docs/libcurl/opts/CURLINFO_CONTENT_TYPE.md b/docs/libcurl/opts/CURLINFO_CONTENT_TYPE.md index 8a9093ced2ff..8de0a654612a 100644 --- a/docs/libcurl/opts/CURLINFO_CONTENT_TYPE.md +++ b/docs/libcurl/opts/CURLINFO_CONTENT_TYPE.md @@ -16,7 +16,7 @@ Added-in: 7.9.4 # NAME -CURLINFO_CONTENT_TYPE - get Content-Type +CURLINFO_CONTENT_TYPE - Content-Type of response # SYNOPSIS @@ -49,16 +49,16 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { /* extract the content-type */ char *ct = NULL; - res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct); - if(!res && ct) { + result = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct); + if(!result && ct) { printf("Content-Type: %s\n", ct); } } diff --git a/docs/libcurl/opts/CURLINFO_COOKIELIST.md b/docs/libcurl/opts/CURLINFO_COOKIELIST.md index b0074b990bc4..d3c4a6590e7d 100644 --- a/docs/libcurl/opts/CURLINFO_COOKIELIST.md +++ b/docs/libcurl/opts/CURLINFO_COOKIELIST.md @@ -15,7 +15,7 @@ Added-in: 7.14.1 # NAME -CURLINFO_COOKIELIST - get all known cookies +CURLINFO_COOKIELIST - all known cookies # SYNOPSIS @@ -46,19 +46,19 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); /* enable the cookie engine */ curl_easy_setopt(curl, CURLOPT_COOKIEFILE, ""); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { /* extract all known cookies */ struct curl_slist *cookies = NULL; - res = curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies); - if(!res && cookies) { + result = curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies); + if(!result && cookies) { /* a linked list of cookies in cookie file format */ struct curl_slist *each = cookies; while(each) { diff --git a/docs/libcurl/opts/CURLINFO_EARLYDATA_SENT_T.md b/docs/libcurl/opts/CURLINFO_EARLYDATA_SENT_T.md index 6855572970d1..c2cb4a558ea0 100644 --- a/docs/libcurl/opts/CURLINFO_EARLYDATA_SENT_T.md +++ b/docs/libcurl/opts/CURLINFO_EARLYDATA_SENT_T.md @@ -16,7 +16,7 @@ Added-in: 8.11.0 # NAME -CURLINFO_EARLYDATA_SENT_T - get the number of bytes sent as TLS early data +CURLINFO_EARLYDATA_SENT_T - number of bytes sent as TLS early data # SYNOPSIS @@ -51,16 +51,16 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); /* Perform the request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { curl_off_t amount; - res = curl_easy_getinfo(curl, CURLINFO_EARLYDATA_SENT_T, &amount); - if(!res) { + result = curl_easy_getinfo(curl, CURLINFO_EARLYDATA_SENT_T, &amount); + if(!result) { printf("TLS earlydata: %" CURL_FORMAT_CURL_OFF_T " bytes\n", amount); } } diff --git a/docs/libcurl/opts/CURLINFO_EFFECTIVE_METHOD.md b/docs/libcurl/opts/CURLINFO_EFFECTIVE_METHOD.md index 5299dab8c16e..5a1fcdc3e41e 100644 --- a/docs/libcurl/opts/CURLINFO_EFFECTIVE_METHOD.md +++ b/docs/libcurl/opts/CURLINFO_EFFECTIVE_METHOD.md @@ -16,7 +16,7 @@ Added-in: 7.72.0 # NAME -CURLINFO_EFFECTIVE_METHOD - get the last used HTTP method +CURLINFO_EFFECTIVE_METHOD - last used HTTP request method # SYNOPSIS @@ -48,12 +48,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(result == CURLE_OK) { char *method = NULL; curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_METHOD, &method); if(method) diff --git a/docs/libcurl/opts/CURLINFO_EFFECTIVE_URL.md b/docs/libcurl/opts/CURLINFO_EFFECTIVE_URL.md index 172f6de3d46b..f7adcd810b63 100644 --- a/docs/libcurl/opts/CURLINFO_EFFECTIVE_URL.md +++ b/docs/libcurl/opts/CURLINFO_EFFECTIVE_URL.md @@ -15,7 +15,7 @@ Added-in: 7.4 # NAME -CURLINFO_EFFECTIVE_URL - get the last used URL +CURLINFO_EFFECTIVE_URL - last used URL # SYNOPSIS @@ -45,11 +45,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(result == CURLE_OK) { char *url = NULL; curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url); if(url) diff --git a/docs/libcurl/opts/CURLINFO_FILETIME.md b/docs/libcurl/opts/CURLINFO_FILETIME.md index 9d4c414d5407..48f3f886a50f 100644 --- a/docs/libcurl/opts/CURLINFO_FILETIME.md +++ b/docs/libcurl/opts/CURLINFO_FILETIME.md @@ -17,7 +17,7 @@ Added-in: 7.5 # NAME -CURLINFO_FILETIME - get the remote time of the retrieved document +CURLINFO_FILETIME - remote time of the retrieved document # SYNOPSIS @@ -50,15 +50,15 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(CURLE_OK == result) { long filetime = 0; - res = curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime); - if((CURLE_OK == res) && (filetime != -1)) { + result = curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime); + if((CURLE_OK == result) && (filetime != -1)) { time_t file_time = (time_t)filetime; printf("filetime: %s", ctime(&file_time)); } diff --git a/docs/libcurl/opts/CURLINFO_FILETIME_T.md b/docs/libcurl/opts/CURLINFO_FILETIME_T.md index 2d15ba88d49f..e1f896e3ea25 100644 --- a/docs/libcurl/opts/CURLINFO_FILETIME_T.md +++ b/docs/libcurl/opts/CURLINFO_FILETIME_T.md @@ -17,7 +17,7 @@ Added-in: 7.59.0 # NAME -CURLINFO_FILETIME_T - get the remote time of the retrieved document +CURLINFO_FILETIME_T - remote time of the retrieved resource # SYNOPSIS @@ -51,15 +51,15 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(CURLE_OK == result) { curl_off_t filetime; - res = curl_easy_getinfo(curl, CURLINFO_FILETIME_T, &filetime); - if((CURLE_OK == res) && (filetime != -1)) { + result = curl_easy_getinfo(curl, CURLINFO_FILETIME_T, &filetime); + if((CURLE_OK == result) && (filetime != -1)) { time_t file_time = (time_t)filetime; printf("filetime: %s", ctime(&file_time)); } diff --git a/docs/libcurl/opts/CURLINFO_FTP_ENTRY_PATH.md b/docs/libcurl/opts/CURLINFO_FTP_ENTRY_PATH.md index db053e311e75..058d273ba04d 100644 --- a/docs/libcurl/opts/CURLINFO_FTP_ENTRY_PATH.md +++ b/docs/libcurl/opts/CURLINFO_FTP_ENTRY_PATH.md @@ -15,7 +15,7 @@ Added-in: 7.15.4 # NAME -CURLINFO_FTP_ENTRY_PATH - get entry path in FTP server +CURLINFO_FTP_ENTRY_PATH - entry path in FTP server # SYNOPSIS @@ -45,16 +45,16 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { /* extract the entry path */ char *ep = NULL; - res = curl_easy_getinfo(curl, CURLINFO_FTP_ENTRY_PATH, &ep); - if(!res && ep) { + result = curl_easy_getinfo(curl, CURLINFO_FTP_ENTRY_PATH, &ep); + if(!result && ep) { printf("Entry path was: %s\n", ep); } } diff --git a/docs/libcurl/opts/CURLINFO_HEADER_SIZE.md b/docs/libcurl/opts/CURLINFO_HEADER_SIZE.md index 85907f3b09ff..a537f0408e73 100644 --- a/docs/libcurl/opts/CURLINFO_HEADER_SIZE.md +++ b/docs/libcurl/opts/CURLINFO_HEADER_SIZE.md @@ -16,7 +16,7 @@ Added-in: 7.4.1 # NAME -CURLINFO_HEADER_SIZE - get size of retrieved headers +CURLINFO_HEADER_SIZE - size of response headers # SYNOPSIS @@ -43,13 +43,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); - res = curl_easy_perform(curl); - if(res == CURLE_OK) { + result = curl_easy_perform(curl); + if(result == CURLE_OK) { long size; - res = curl_easy_getinfo(curl, CURLINFO_HEADER_SIZE, &size); - if(!res) + result = curl_easy_getinfo(curl, CURLINFO_HEADER_SIZE, &size); + if(!result) printf("Header size: %ld bytes\n", size); } curl_easy_cleanup(curl); diff --git a/docs/libcurl/opts/CURLINFO_HTTPAUTH_AVAIL.md b/docs/libcurl/opts/CURLINFO_HTTPAUTH_AVAIL.md index 4d001fb4b6f5..8829227c9816 100644 --- a/docs/libcurl/opts/CURLINFO_HTTPAUTH_AVAIL.md +++ b/docs/libcurl/opts/CURLINFO_HTTPAUTH_AVAIL.md @@ -16,7 +16,7 @@ Added-in: 7.10.8 # NAME -CURLINFO_HTTPAUTH_AVAIL - get available HTTP authentication methods +CURLINFO_HTTPAUTH_AVAIL - available HTTP authentication methods # SYNOPSIS @@ -41,16 +41,16 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { /* extract the available authentication types */ long auth; - res = curl_easy_getinfo(curl, CURLINFO_HTTPAUTH_AVAIL, &auth); - if(!res) { + result = curl_easy_getinfo(curl, CURLINFO_HTTPAUTH_AVAIL, &auth); + if(!result) { if(!auth) printf("No auth available, perhaps no 401?\n"); else { diff --git a/docs/libcurl/opts/CURLINFO_HTTPAUTH_USED.md b/docs/libcurl/opts/CURLINFO_HTTPAUTH_USED.md index 9b6312171021..031691402b34 100644 --- a/docs/libcurl/opts/CURLINFO_HTTPAUTH_USED.md +++ b/docs/libcurl/opts/CURLINFO_HTTPAUTH_USED.md @@ -15,7 +15,7 @@ Added-in: 8.12.0 # NAME -CURLINFO_HTTPAUTH_USED - get used HTTP authentication method +CURLINFO_HTTPAUTH_USED - used HTTP authentication method # SYNOPSIS @@ -42,18 +42,18 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC | CURLAUTH_DIGEST); curl_easy_setopt(curl, CURLOPT_USERNAME, "shrek"); curl_easy_setopt(curl, CURLOPT_PASSWORD, "swamp"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { long auth; - res = curl_easy_getinfo(curl, CURLINFO_HTTPAUTH_USED, &auth); - if(!res) { + result = curl_easy_getinfo(curl, CURLINFO_HTTPAUTH_USED, &auth); + if(!result) { if(!auth) printf("No auth used\n"); else { diff --git a/docs/libcurl/opts/CURLINFO_HTTP_CONNECTCODE.md b/docs/libcurl/opts/CURLINFO_HTTP_CONNECTCODE.md index a9231289c035..2ded9a121be4 100644 --- a/docs/libcurl/opts/CURLINFO_HTTP_CONNECTCODE.md +++ b/docs/libcurl/opts/CURLINFO_HTTP_CONNECTCODE.md @@ -15,7 +15,7 @@ Added-in: 7.10.7 # NAME -CURLINFO_HTTP_CONNECTCODE - get the CONNECT response code +CURLINFO_HTTP_CONNECTCODE - CONNECT response code # SYNOPSIS @@ -40,16 +40,16 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(result == CURLE_OK) { long code; - res = curl_easy_getinfo(curl, CURLINFO_HTTP_CONNECTCODE, &code); - if(!res && code) + result = curl_easy_getinfo(curl, CURLINFO_HTTP_CONNECTCODE, &code); + if(!result && code) printf("The CONNECT response code: %03ld\n", code); } curl_easy_cleanup(curl); diff --git a/docs/libcurl/opts/CURLINFO_HTTP_VERSION.md b/docs/libcurl/opts/CURLINFO_HTTP_VERSION.md index 8fddc14f0790..0062a043d895 100644 --- a/docs/libcurl/opts/CURLINFO_HTTP_VERSION.md +++ b/docs/libcurl/opts/CURLINFO_HTTP_VERSION.md @@ -15,7 +15,7 @@ Added-in: 7.50.0 # NAME -CURLINFO_HTTP_VERSION - get the http version used in the connection +CURLINFO_HTTP_VERSION - HTTP version used in the transfer # SYNOPSIS @@ -27,10 +27,10 @@ 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. +Pass a pointer to a long to receive the version used in the last http transfer +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% @@ -41,10 +41,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); - res = curl_easy_perform(curl); - if(res == CURLE_OK) { + result = curl_easy_perform(curl); + if(result == CURLE_OK) { long http_version; curl_easy_getinfo(curl, CURLINFO_HTTP_VERSION, &http_version); } diff --git a/docs/libcurl/opts/CURLINFO_LASTSOCKET.md b/docs/libcurl/opts/CURLINFO_LASTSOCKET.md index 1b4a22d65048..8aa80f9fc5e8 100644 --- a/docs/libcurl/opts/CURLINFO_LASTSOCKET.md +++ b/docs/libcurl/opts/CURLINFO_LASTSOCKET.md @@ -16,7 +16,7 @@ Added-in: 7.15.2 # NAME -CURLINFO_LASTSOCKET - get the last socket used +CURLINFO_LASTSOCKET - last socket used # SYNOPSIS @@ -50,22 +50,22 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); - if(res != CURLE_OK) { - printf("Error: %s\n", curl_easy_strerror(res)); + result = curl_easy_perform(curl); + if(result != CURLE_OK) { + printf("Error: %s\n", curl_easy_strerror(result)); curl_easy_cleanup(curl); return 1; } /* Extract the socket from the curl handle */ - res = curl_easy_getinfo(curl, CURLINFO_LASTSOCKET, &sockfd); - if(!res && sockfd != -1) { + result = curl_easy_getinfo(curl, CURLINFO_LASTSOCKET, &sockfd); + if(!result && sockfd != -1) { /* operate on sockfd */ } diff --git a/docs/libcurl/opts/CURLINFO_LOCAL_IP.md b/docs/libcurl/opts/CURLINFO_LOCAL_IP.md index c626815c9003..270b7d5f269d 100644 --- a/docs/libcurl/opts/CURLINFO_LOCAL_IP.md +++ b/docs/libcurl/opts/CURLINFO_LOCAL_IP.md @@ -17,7 +17,7 @@ Added-in: 7.21.0 # NAME -CURLINFO_LOCAL_IP - get local IP address of last connection +CURLINFO_LOCAL_IP - local IP address of last connection # SYNOPSIS @@ -47,15 +47,15 @@ the corresponding curl handle. int main(void) { char *ip; - CURLcode res; + CURLcode result; CURL *curl = curl_easy_init(); curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); /* Perform the transfer */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if((res == CURLE_OK) && + if((result == CURLE_OK) && !curl_easy_getinfo(curl, CURLINFO_LOCAL_IP, &ip) && ip) { printf("Local IP: %s\n", ip); } diff --git a/docs/libcurl/opts/CURLINFO_LOCAL_PORT.md b/docs/libcurl/opts/CURLINFO_LOCAL_PORT.md index 937327f45e99..a292f8883fff 100644 --- a/docs/libcurl/opts/CURLINFO_LOCAL_PORT.md +++ b/docs/libcurl/opts/CURLINFO_LOCAL_PORT.md @@ -17,7 +17,7 @@ Added-in: 7.21.0 # NAME -CURLINFO_LOCAL_PORT - get the latest local port number +CURLINFO_LOCAL_PORT - latest local port number # SYNOPSIS @@ -35,6 +35,9 @@ connection done with this **curl** handle. If the connection was done using QUIC, the port number is a UDP port number, otherwise it is a TCP port number. +If no connection was established or if the protocol does not use ports, -1 +is returned. + # %PROTOCOLS% # EXAMPLE @@ -43,18 +46,18 @@ otherwise it is a TCP port number. int main(void) { CURL *curl; - CURLcode res; + CURLcode result; curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(CURLE_OK == res) { + if(CURLE_OK == result) { long port; - res = curl_easy_getinfo(curl, CURLINFO_LOCAL_PORT, &port); + result = curl_easy_getinfo(curl, CURLINFO_LOCAL_PORT, &port); - if(CURLE_OK == res) { + if(CURLE_OK == result) { printf("We used local port: %ld\n", port); } } diff --git a/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME.md b/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME.md index fe29e0c4369b..c37b36d31df4 100644 --- a/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME.md +++ b/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME.md @@ -15,7 +15,7 @@ Added-in: 7.4.1 # NAME -CURLINFO_NAMELOOKUP_TIME - get the name lookup time +CURLINFO_NAMELOOKUP_TIME - name lookup time # SYNOPSIS @@ -44,13 +44,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(CURLE_OK == result) { + result = curl_easy_getinfo(curl, CURLINFO_NAMELOOKUP_TIME, &namelookup); + if(CURLE_OK == result) { printf("Time: %.1f", namelookup); } } diff --git a/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME_T.md b/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME_T.md index 7b34ef5c0c96..152abd281f4b 100644 --- a/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME_T.md +++ b/docs/libcurl/opts/CURLINFO_NAMELOOKUP_TIME_T.md @@ -15,7 +15,7 @@ Added-in: 7.61.0 # NAME -CURLINFO_NAMELOOKUP_TIME_T - get the name lookup time in microseconds +CURLINFO_NAMELOOKUP_TIME_T - name lookup time in microseconds # SYNOPSIS @@ -44,13 +44,14 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(CURLE_OK == result) { + result = curl_easy_getinfo(curl, CURLINFO_NAMELOOKUP_TIME_T, + &namelookup); + if(CURLE_OK == result) { printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld", namelookup / 1000000, (long)(namelookup % 1000000)); } diff --git a/docs/libcurl/opts/CURLINFO_NUM_CONNECTS.md b/docs/libcurl/opts/CURLINFO_NUM_CONNECTS.md index eefb38ea75aa..dfac4409790c 100644 --- a/docs/libcurl/opts/CURLINFO_NUM_CONNECTS.md +++ b/docs/libcurl/opts/CURLINFO_NUM_CONNECTS.md @@ -14,7 +14,7 @@ Added-in: 7.12.3 # NAME -CURLINFO_NUM_CONNECTS - get number of created connections +CURLINFO_NUM_CONNECTS - number of created connections # SYNOPSIS @@ -42,14 +42,14 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(result == CURLE_OK) { long connects; - res = curl_easy_getinfo(curl, CURLINFO_NUM_CONNECTS, &connects); - if(!res) + result = curl_easy_getinfo(curl, CURLINFO_NUM_CONNECTS, &connects); + if(!result) printf("It needed %ld connects\n", connects); } curl_easy_cleanup(curl); diff --git a/docs/libcurl/opts/CURLINFO_OS_ERRNO.md b/docs/libcurl/opts/CURLINFO_OS_ERRNO.md index 25ddd6221e06..f163a418191d 100644 --- a/docs/libcurl/opts/CURLINFO_OS_ERRNO.md +++ b/docs/libcurl/opts/CURLINFO_OS_ERRNO.md @@ -14,7 +14,7 @@ Added-in: 7.12.2 # NAME -CURLINFO_OS_ERRNO - get errno number from last connect failure +CURLINFO_OS_ERRNO - errno number from last connect failure # SYNOPSIS @@ -47,13 +47,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); - res = curl_easy_perform(curl); - if(res != CURLE_OK) { + result = curl_easy_perform(curl); + if(result != CURLE_OK) { long error; - res = curl_easy_getinfo(curl, CURLINFO_OS_ERRNO, &error); - if(!res && error) { + result = curl_easy_getinfo(curl, CURLINFO_OS_ERRNO, &error); + if(!result && error) { printf("Errno: %ld\n", error); } } diff --git a/docs/libcurl/opts/CURLINFO_POSTTRANSFER_TIME_T.md b/docs/libcurl/opts/CURLINFO_POSTTRANSFER_TIME_T.md index e5f1b5002f4d..6819684908b2 100644 --- a/docs/libcurl/opts/CURLINFO_POSTTRANSFER_TIME_T.md +++ b/docs/libcurl/opts/CURLINFO_POSTTRANSFER_TIME_T.md @@ -16,7 +16,7 @@ Added-in: 8.10.0 # NAME -CURLINFO_POSTTRANSFER_TIME_T - get the time until the last byte is sent +CURLINFO_POSTTRANSFER_TIME_T - time to last byte sent # SYNOPSIS @@ -45,15 +45,15 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); - res = curl_easy_perform(curl); - if(CURLE_OK == res) { + result = curl_easy_perform(curl); + if(CURLE_OK == result) { curl_off_t posttransfer; - res = curl_easy_getinfo(curl, CURLINFO_POSTTRANSFER_TIME_T, + result = curl_easy_getinfo(curl, CURLINFO_POSTTRANSFER_TIME_T, &posttransfer); - if(CURLE_OK == res) { - printf("Request sent after: %" CURL_FORMAT_CURL_OFF_T ".%06ld us", + if(CURLE_OK == result) { + printf("Request sent after: %" CURL_FORMAT_CURL_OFF_T ".%06ld s", posttransfer / 1000000, (long)(posttransfer % 1000000)); } } diff --git a/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME.md b/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME.md index 9442d19c0ab7..297cf06ca590 100644 --- a/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME.md +++ b/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME.md @@ -16,7 +16,7 @@ Added-in: 7.4.1 # NAME -CURLINFO_PRETRANSFER_TIME - get the time until the file transfer start +CURLINFO_PRETRANSFER_TIME - time to transfer start # SYNOPSIS @@ -49,13 +49,14 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(CURLE_OK == result) { + result = curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME, + &pretransfer); + if(CURLE_OK == result) { printf("Time: %.1f", pretransfer); } } diff --git a/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME_T.md b/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME_T.md index 2147f2796984..43680edcf8f5 100644 --- a/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME_T.md +++ b/docs/libcurl/opts/CURLINFO_PRETRANSFER_TIME_T.md @@ -16,7 +16,7 @@ Added-in: 7.61.0 # NAME -CURLINFO_PRETRANSFER_TIME_T - get the time until the file transfer start +CURLINFO_PRETRANSFER_TIME_T - time to transfer start # SYNOPSIS @@ -49,13 +49,14 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(CURLE_OK == result) { + result = curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME_T, + &pretransfer); + if(CURLE_OK == result) { printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld\n", pretransfer / 1000000, (long)(pretransfer % 1000000)); diff --git a/docs/libcurl/opts/CURLINFO_PRIMARY_IP.md b/docs/libcurl/opts/CURLINFO_PRIMARY_IP.md index 1fdb130711e4..683d97de16a5 100644 --- a/docs/libcurl/opts/CURLINFO_PRIMARY_IP.md +++ b/docs/libcurl/opts/CURLINFO_PRIMARY_IP.md @@ -17,7 +17,7 @@ Added-in: 7.19.0 # NAME -CURLINFO_PRIMARY_IP - get IP address of last connection +CURLINFO_PRIMARY_IP - IP address of last connection # SYNOPSIS @@ -47,15 +47,15 @@ the corresponding curl handle. int main(void) { char *ip; - CURLcode res; + CURLcode result; CURL *curl = curl_easy_init(); curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); /* Perform the transfer */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if((res == CURLE_OK) && + if((result == CURLE_OK) && !curl_easy_getinfo(curl, CURLINFO_PRIMARY_IP, &ip) && ip) { printf("IP: %s\n", ip); } diff --git a/docs/libcurl/opts/CURLINFO_PRIMARY_PORT.md b/docs/libcurl/opts/CURLINFO_PRIMARY_PORT.md index d0bb632f44dd..58b8c0d1b44e 100644 --- a/docs/libcurl/opts/CURLINFO_PRIMARY_PORT.md +++ b/docs/libcurl/opts/CURLINFO_PRIMARY_PORT.md @@ -16,7 +16,7 @@ Added-in: 7.21.0 # NAME -CURLINFO_PRIMARY_PORT - get the latest destination port number +CURLINFO_PRIMARY_PORT - last destination port number # SYNOPSIS @@ -36,6 +36,11 @@ 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. +If the connection was done using QUIC, the port number is a UDP port number. + +If no connection was established or if the protocol does not use ports, -1 +is returned. + # %PROTOCOLS% # EXAMPLE @@ -45,13 +50,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); - res = curl_easy_perform(curl); - if(res == CURLE_OK) { + result = curl_easy_perform(curl); + if(result == CURLE_OK) { long port; - res = curl_easy_getinfo(curl, CURLINFO_PRIMARY_PORT, &port); - if(!res) + result = curl_easy_getinfo(curl, CURLINFO_PRIMARY_PORT, &port); + if(!result) printf("Connected to remote port: %ld\n", port); } curl_easy_cleanup(curl); diff --git a/docs/libcurl/opts/CURLINFO_PRIVATE.md b/docs/libcurl/opts/CURLINFO_PRIVATE.md index 7d4aff10f7d3..ac4fb82e154c 100644 --- a/docs/libcurl/opts/CURLINFO_PRIVATE.md +++ b/docs/libcurl/opts/CURLINFO_PRIVATE.md @@ -15,7 +15,7 @@ Added-in: 7.10.3 # NAME -CURLINFO_PRIVATE - get the private pointer +CURLINFO_PRIVATE - private pointer # SYNOPSIS @@ -41,19 +41,19 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); /* extract the private pointer again */ - res = curl_easy_getinfo(curl, CURLINFO_PRIVATE, &pointer); + result = curl_easy_getinfo(curl, CURLINFO_PRIVATE, &pointer); - if(res) - printf("error: %s\n", curl_easy_strerror(res)); + if(result) + printf("error: %s\n", curl_easy_strerror(result)); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLINFO_PROTOCOL.md b/docs/libcurl/opts/CURLINFO_PROTOCOL.md index a472a3d80832..3f9346fa049b 100644 --- a/docs/libcurl/opts/CURLINFO_PROTOCOL.md +++ b/docs/libcurl/opts/CURLINFO_PROTOCOL.md @@ -15,7 +15,7 @@ Added-in: 7.52.0 # NAME -CURLINFO_PROTOCOL - get the protocol used in the connection +CURLINFO_PROTOCOL - URL scheme used in transfer # SYNOPSIS @@ -27,12 +27,12 @@ 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. +This option is deprecated. We strongly recommend using CURLINFO_SCHEME(3) +instead, because this option cannot return all possible schemes. The scheme +might also sometimes be referred to as the protocol. -Pass a pointer to a long to receive the version used in the last http -connection. The returned value is set to one of these values: +Pass a pointer to a long to receive the scheme used in the last transfer. The +returned value is set to one of these values: ~~~c CURLPROTO_DICT, CURLPROTO_FILE, CURLPROTO_FTP, CURLPROTO_FTPS, @@ -53,12 +53,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); + if(result == CURLE_OK) { + long scheme; + curl_easy_getinfo(curl, CURLINFO_PROTOCOL, &scheme); } curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLINFO_PROXYAUTH_AVAIL.md b/docs/libcurl/opts/CURLINFO_PROXYAUTH_AVAIL.md index c30794f27886..16161aabee3a 100644 --- a/docs/libcurl/opts/CURLINFO_PROXYAUTH_AVAIL.md +++ b/docs/libcurl/opts/CURLINFO_PROXYAUTH_AVAIL.md @@ -15,7 +15,7 @@ Added-in: 7.10.8 # NAME -CURLINFO_PROXYAUTH_AVAIL - get available HTTP proxy authentication methods +CURLINFO_PROXYAUTH_AVAIL - HTTP proxy authentication methods # SYNOPSIS @@ -41,17 +41,17 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { /* extract the available proxy authentication types */ long auth; - res = curl_easy_getinfo(curl, CURLINFO_PROXYAUTH_AVAIL, &auth); - if(!res) { + result = curl_easy_getinfo(curl, CURLINFO_PROXYAUTH_AVAIL, &auth); + if(!result) { if(!auth) printf("No proxy auth available, perhaps no 407?\n"); else { diff --git a/docs/libcurl/opts/CURLINFO_PROXYAUTH_USED.md b/docs/libcurl/opts/CURLINFO_PROXYAUTH_USED.md index c4a9c943afc5..e0788c63f212 100644 --- a/docs/libcurl/opts/CURLINFO_PROXYAUTH_USED.md +++ b/docs/libcurl/opts/CURLINFO_PROXYAUTH_USED.md @@ -15,7 +15,7 @@ Added-in: 8.12.0 # NAME -CURLINFO_PROXYAUTH_USED - get used HTTP proxy authentication method +CURLINFO_PROXYAUTH_USED - HTTP proxy authentication method # SYNOPSIS @@ -43,20 +43,20 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); - curl_easy_setopt(curl, CURLOPT_PROXY, "http://proxy.example.com"); + curl_easy_setopt(curl, CURLOPT_PROXY, "http://proxy.example"); curl_easy_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_BASIC | CURLAUTH_DIGEST); curl_easy_setopt(curl, CURLOPT_PROXYUSERNAME, "shrek"); curl_easy_setopt(curl, CURLOPT_PROXYPASSWORD, "swamp"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { long auth; - res = curl_easy_getinfo(curl, CURLINFO_PROXYAUTH_USED, &auth); - if(!res) { + result = curl_easy_getinfo(curl, CURLINFO_PROXYAUTH_USED, &auth); + if(!result) { if(!auth) printf("No auth used\n"); else { diff --git a/docs/libcurl/opts/CURLINFO_PROXY_ERROR.md b/docs/libcurl/opts/CURLINFO_PROXY_ERROR.md index 772fa7cb755d..0c2dab38fd7b 100644 --- a/docs/libcurl/opts/CURLINFO_PROXY_ERROR.md +++ b/docs/libcurl/opts/CURLINFO_PROXY_ERROR.md @@ -16,7 +16,7 @@ Added-in: 7.73.0 # NAME -CURLINFO_PROXY_ERROR - get the detailed (SOCKS) proxy error +CURLINFO_PROXY_ERROR - detailed (SOCKS) proxy error # SYNOPSIS @@ -81,15 +81,15 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(result == CURLE_PROXY) { long proxycode; - res = curl_easy_getinfo(curl, CURLINFO_PROXY_ERROR, &proxycode); - if(!res && proxycode) + result = curl_easy_getinfo(curl, CURLINFO_PROXY_ERROR, &proxycode); + if(!result && proxycode) printf("The detailed proxy error: %ld\n", proxycode); } curl_easy_cleanup(curl); diff --git a/docs/libcurl/opts/CURLINFO_PROXY_SSL_VERIFYRESULT.md b/docs/libcurl/opts/CURLINFO_PROXY_SSL_VERIFYRESULT.md index dd65c4214bf0..6164eaeafdee 100644 --- a/docs/libcurl/opts/CURLINFO_PROXY_SSL_VERIFYRESULT.md +++ b/docs/libcurl/opts/CURLINFO_PROXY_SSL_VERIFYRESULT.md @@ -18,7 +18,7 @@ Added-in: 7.52.0 # NAME -CURLINFO_PROXY_SSL_VERIFYRESULT - get the result of the proxy certificate verification +CURLINFO_PROXY_SSL_VERIFYRESULT - result of proxy certificate verification # SYNOPSIS @@ -46,22 +46,22 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; long verifyresult; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); - curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy:443"); + curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy.example:443"); - res = curl_easy_perform(curl); - if(res) { - printf("error: %s\n", curl_easy_strerror(res)); + result = curl_easy_perform(curl); + if(result) { + printf("error: %s\n", curl_easy_strerror(result)); curl_easy_cleanup(curl); return 1; } - res = curl_easy_getinfo(curl, CURLINFO_PROXY_SSL_VERIFYRESULT, - &verifyresult); - if(!res) { + result = curl_easy_getinfo(curl, CURLINFO_PROXY_SSL_VERIFYRESULT, + &verifyresult); + if(!result) { printf("The peer verification said %s\n", (verifyresult ? "bad" : "fine")); } diff --git a/docs/libcurl/opts/CURLINFO_QUEUE_TIME_T.md b/docs/libcurl/opts/CURLINFO_QUEUE_TIME_T.md index acf916413137..d7521c1d5d29 100644 --- a/docs/libcurl/opts/CURLINFO_QUEUE_TIME_T.md +++ b/docs/libcurl/opts/CURLINFO_QUEUE_TIME_T.md @@ -45,13 +45,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(CURLE_OK == result) { + result = curl_easy_getinfo(curl, CURLINFO_QUEUE_TIME_T, &queue); + if(CURLE_OK == result) { printf("Queued: %" CURL_FORMAT_CURL_OFF_T ".%06ld us", queue / 1000000, (long)(queue % 1000000)); } diff --git a/docs/libcurl/opts/CURLINFO_REDIRECT_COUNT.md b/docs/libcurl/opts/CURLINFO_REDIRECT_COUNT.md index 3f58cc09c4bd..c4796e4c9637 100644 --- a/docs/libcurl/opts/CURLINFO_REDIRECT_COUNT.md +++ b/docs/libcurl/opts/CURLINFO_REDIRECT_COUNT.md @@ -16,7 +16,7 @@ Added-in: 7.9.7 # NAME -CURLINFO_REDIRECT_COUNT - get the number of redirects +CURLINFO_REDIRECT_COUNT - number of redirects # SYNOPSIS @@ -41,11 +41,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(result == CURLE_OK) { long redirects; curl_easy_getinfo(curl, CURLINFO_REDIRECT_COUNT, &redirects); } diff --git a/docs/libcurl/opts/CURLINFO_REDIRECT_TIME.md b/docs/libcurl/opts/CURLINFO_REDIRECT_TIME.md index f0b79e261feb..01d99f8aeb55 100644 --- a/docs/libcurl/opts/CURLINFO_REDIRECT_TIME.md +++ b/docs/libcurl/opts/CURLINFO_REDIRECT_TIME.md @@ -17,7 +17,7 @@ Added-in: 7.9.7 # NAME -CURLINFO_REDIRECT_TIME - get the time for all redirection steps +CURLINFO_REDIRECT_TIME - time for all redirection steps # SYNOPSIS @@ -46,13 +46,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(CURLE_OK == result) { + result = curl_easy_getinfo(curl, CURLINFO_REDIRECT_TIME, &redirect); + if(CURLE_OK == result) { printf("Time: %.1f", redirect); } } diff --git a/docs/libcurl/opts/CURLINFO_REDIRECT_TIME_T.md b/docs/libcurl/opts/CURLINFO_REDIRECT_TIME_T.md index 88a0830d3726..5b3875f8d7c4 100644 --- a/docs/libcurl/opts/CURLINFO_REDIRECT_TIME_T.md +++ b/docs/libcurl/opts/CURLINFO_REDIRECT_TIME_T.md @@ -17,7 +17,7 @@ Added-in: 7.61.0 # NAME -CURLINFO_REDIRECT_TIME_T - get the time for all redirection steps +CURLINFO_REDIRECT_TIME_T - time for all redirection steps # SYNOPSIS @@ -47,13 +47,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(CURLE_OK == result) { + result = curl_easy_getinfo(curl, CURLINFO_REDIRECT_TIME_T, &redirect); + if(CURLE_OK == result) { printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld", redirect / 1000000, (long)(redirect % 1000000)); } diff --git a/docs/libcurl/opts/CURLINFO_REDIRECT_URL.md b/docs/libcurl/opts/CURLINFO_REDIRECT_URL.md index d1197e0b28ac..32ec6c3355d9 100644 --- a/docs/libcurl/opts/CURLINFO_REDIRECT_URL.md +++ b/docs/libcurl/opts/CURLINFO_REDIRECT_URL.md @@ -17,7 +17,7 @@ Added-in: 7.18.2 # NAME -CURLINFO_REDIRECT_URL - get the URL a redirect would go to +CURLINFO_REDIRECT_URL - URL a redirect would go to # SYNOPSIS @@ -47,10 +47,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); - res = curl_easy_perform(curl); - if(res == CURLE_OK) { + result = curl_easy_perform(curl); + if(result == CURLE_OK) { char *url = NULL; curl_easy_getinfo(curl, CURLINFO_REDIRECT_URL, &url); if(url) diff --git a/docs/libcurl/opts/CURLINFO_REFERER.md b/docs/libcurl/opts/CURLINFO_REFERER.md index 17b9db1a18a3..6542965fa948 100644 --- a/docs/libcurl/opts/CURLINFO_REFERER.md +++ b/docs/libcurl/opts/CURLINFO_REFERER.md @@ -16,7 +16,7 @@ Added-in: 7.76.0 # NAME -CURLINFO_REFERER - get the used referrer request header +CURLINFO_REFERER - used HTTP referrer request header # SYNOPSIS @@ -44,11 +44,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(result == CURLE_OK) { char *hdr = NULL; curl_easy_getinfo(curl, CURLINFO_REFERER, &hdr); if(hdr) diff --git a/docs/libcurl/opts/CURLINFO_REQUEST_SIZE.md b/docs/libcurl/opts/CURLINFO_REQUEST_SIZE.md index fedefc0cc61e..9657f3de6012 100644 --- a/docs/libcurl/opts/CURLINFO_REQUEST_SIZE.md +++ b/docs/libcurl/opts/CURLINFO_REQUEST_SIZE.md @@ -16,7 +16,7 @@ Added-in: 7.4.1 # NAME -CURLINFO_REQUEST_SIZE - get size of sent request +CURLINFO_REQUEST_SIZE - size of sent request # SYNOPSIS @@ -41,13 +41,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); - res = curl_easy_perform(curl); - if(res == CURLE_OK) { + result = curl_easy_perform(curl); + if(result == CURLE_OK) { long req; - res = curl_easy_getinfo(curl, CURLINFO_REQUEST_SIZE, &req); - if(!res) + result = curl_easy_getinfo(curl, CURLINFO_REQUEST_SIZE, &req); + if(!result) printf("Request size: %ld bytes\n", req); } curl_easy_cleanup(curl); diff --git a/docs/libcurl/opts/CURLINFO_RESPONSE_CODE.md b/docs/libcurl/opts/CURLINFO_RESPONSE_CODE.md index db75eb94a096..aeb8aeab8a20 100644 --- a/docs/libcurl/opts/CURLINFO_RESPONSE_CODE.md +++ b/docs/libcurl/opts/CURLINFO_RESPONSE_CODE.md @@ -18,7 +18,7 @@ Added-in: 7.10.8 # NAME -CURLINFO_RESPONSE_CODE - get the last response code +CURLINFO_RESPONSE_CODE - last response code # SYNOPSIS @@ -47,10 +47,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); - res = curl_easy_perform(curl); - if(res == CURLE_OK) { + result = curl_easy_perform(curl); + if(result == CURLE_OK) { long response_code; curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code); } diff --git a/docs/libcurl/opts/CURLINFO_RETRY_AFTER.md b/docs/libcurl/opts/CURLINFO_RETRY_AFTER.md index 0065f3f32dcf..3e36aa3d71ee 100644 --- a/docs/libcurl/opts/CURLINFO_RETRY_AFTER.md +++ b/docs/libcurl/opts/CURLINFO_RETRY_AFTER.md @@ -54,10 +54,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); - res = curl_easy_perform(curl); - if(res == CURLE_OK) { + result = curl_easy_perform(curl); + if(result == CURLE_OK) { curl_off_t wait = 0; curl_easy_getinfo(curl, CURLINFO_RETRY_AFTER, &wait); if(wait) diff --git a/docs/libcurl/opts/CURLINFO_RTSP_CLIENT_CSEQ.md b/docs/libcurl/opts/CURLINFO_RTSP_CLIENT_CSEQ.md index 0cfa84b34bcd..a16b5a1ab6d6 100644 --- a/docs/libcurl/opts/CURLINFO_RTSP_CLIENT_CSEQ.md +++ b/docs/libcurl/opts/CURLINFO_RTSP_CLIENT_CSEQ.md @@ -16,7 +16,7 @@ Added-in: 7.20.0 # NAME -CURLINFO_RTSP_CLIENT_CSEQ - get the next RTSP client CSeq +CURLINFO_RTSP_CLIENT_CSEQ - next RTSP client CSeq # SYNOPSIS @@ -41,10 +41,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "rtsp://rtsp.example.com"); - res = curl_easy_perform(curl); - if(res == CURLE_OK) { + result = curl_easy_perform(curl); + if(result == CURLE_OK) { long cseq; curl_easy_getinfo(curl, CURLINFO_RTSP_CLIENT_CSEQ, &cseq); } diff --git a/docs/libcurl/opts/CURLINFO_RTSP_CSEQ_RECV.md b/docs/libcurl/opts/CURLINFO_RTSP_CSEQ_RECV.md index 9de26f0f76bf..98cf8a29aa21 100644 --- a/docs/libcurl/opts/CURLINFO_RTSP_CSEQ_RECV.md +++ b/docs/libcurl/opts/CURLINFO_RTSP_CSEQ_RECV.md @@ -15,7 +15,7 @@ Added-in: 7.20.0 # NAME -CURLINFO_RTSP_CSEQ_RECV - get the recently received CSeq +CURLINFO_RTSP_CSEQ_RECV - last received RTSP CSeq # SYNOPSIS @@ -41,10 +41,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "rtsp://rtsp.example.com"); - res = curl_easy_perform(curl); - if(res == CURLE_OK) { + result = curl_easy_perform(curl); + if(result == CURLE_OK) { long cseq; curl_easy_getinfo(curl, CURLINFO_RTSP_CSEQ_RECV, &cseq); } diff --git a/docs/libcurl/opts/CURLINFO_RTSP_SERVER_CSEQ.md b/docs/libcurl/opts/CURLINFO_RTSP_SERVER_CSEQ.md index 0f3c638f8f39..d7fd2131e0bd 100644 --- a/docs/libcurl/opts/CURLINFO_RTSP_SERVER_CSEQ.md +++ b/docs/libcurl/opts/CURLINFO_RTSP_SERVER_CSEQ.md @@ -15,7 +15,7 @@ Added-in: 7.20.0 # NAME -CURLINFO_RTSP_SERVER_CSEQ - get the next RTSP server CSeq +CURLINFO_RTSP_SERVER_CSEQ - next RTSP server CSeq # SYNOPSIS @@ -45,10 +45,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "rtsp://rtsp.example.com"); - res = curl_easy_perform(curl); - if(res == CURLE_OK) { + result = curl_easy_perform(curl); + if(result == CURLE_OK) { long cseq; curl_easy_getinfo(curl, CURLINFO_RTSP_SERVER_CSEQ, &cseq); } diff --git a/docs/libcurl/opts/CURLINFO_RTSP_SESSION_ID.md b/docs/libcurl/opts/CURLINFO_RTSP_SESSION_ID.md index 121642677b78..4d75ef33e22e 100644 --- a/docs/libcurl/opts/CURLINFO_RTSP_SESSION_ID.md +++ b/docs/libcurl/opts/CURLINFO_RTSP_SESSION_ID.md @@ -15,7 +15,7 @@ Added-in: 7.20.0 # NAME -CURLINFO_RTSP_SESSION_ID - get RTSP session ID +CURLINFO_RTSP_SESSION_ID - RTSP session ID # SYNOPSIS @@ -46,10 +46,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "rtsp://rtsp.example.com"); - res = curl_easy_perform(curl); - if(res == CURLE_OK) { + result = curl_easy_perform(curl); + if(result == CURLE_OK) { char *id; curl_easy_getinfo(curl, CURLINFO_RTSP_SESSION_ID, &id); } diff --git a/docs/libcurl/opts/CURLINFO_SCHEME.md b/docs/libcurl/opts/CURLINFO_SCHEME.md index 1c61849829af..d453e2891d72 100644 --- a/docs/libcurl/opts/CURLINFO_SCHEME.md +++ b/docs/libcurl/opts/CURLINFO_SCHEME.md @@ -17,7 +17,7 @@ Added-in: 7.52.0 # NAME -CURLINFO_SCHEME - get the URL scheme (sometimes called protocol) used in the connection +CURLINFO_SCHEME - URL scheme used in transfer # SYNOPSIS @@ -30,8 +30,9 @@ 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**. +string holding the URL scheme used for the most recent transfer done with this +CURL **handle**. The scheme might also sometimes be referred to as the +protocol. The **scheme** pointer is NULL or points to private memory. You **must not** free it. The memory gets freed automatically when you call @@ -49,10 +50,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); - res = curl_easy_perform(curl); - if(res == CURLE_OK) { + result = curl_easy_perform(curl); + if(result == CURLE_OK) { char *scheme = NULL; curl_easy_getinfo(curl, CURLINFO_SCHEME, &scheme); if(scheme) diff --git a/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD.md b/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD.md index 30dc52b395fd..1b04c27ea933 100644 --- a/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD.md +++ b/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD.md @@ -17,7 +17,7 @@ Added-in: 7.4.1 # NAME -CURLINFO_SIZE_DOWNLOAD - get the number of downloaded bytes +CURLINFO_SIZE_DOWNLOAD - number of downloaded bytes # SYNOPSIS @@ -47,17 +47,17 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); /* Perform the request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { /* check the size */ double dl; - res = curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &dl); - if(!res) { + result = curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &dl); + if(!result) { printf("Downloaded %.0f bytes\n", dl); } } diff --git a/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD_T.md b/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD_T.md index 5d181b12e0f1..0393c4994908 100644 --- a/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD_T.md +++ b/docs/libcurl/opts/CURLINFO_SIZE_DOWNLOAD_T.md @@ -17,7 +17,7 @@ Added-in: 7.55.0 # NAME -CURLINFO_SIZE_DOWNLOAD_T - get the number of downloaded bytes +CURLINFO_SIZE_DOWNLOAD_T - number of downloaded bytes # SYNOPSIS @@ -44,17 +44,17 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); /* Perform the request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { /* check the size */ curl_off_t dl; - res = curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD_T, &dl); - if(!res) { + result = curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD_T, &dl); + if(!result) { printf("Downloaded %" CURL_FORMAT_CURL_OFF_T " bytes\n", dl); } } diff --git a/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD.md b/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD.md index 6e1881271a74..6111db4a5788 100644 --- a/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD.md +++ b/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD.md @@ -16,7 +16,7 @@ Added-in: 7.4.1 # NAME -CURLINFO_SIZE_UPLOAD - get the number of uploaded bytes +CURLINFO_SIZE_UPLOAD - number of uploaded bytes # SYNOPSIS @@ -44,16 +44,16 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); /* Perform the request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { double ul; - res = curl_easy_getinfo(curl, CURLINFO_SIZE_UPLOAD, &ul); - if(!res) { + result = curl_easy_getinfo(curl, CURLINFO_SIZE_UPLOAD, &ul); + if(!result) { printf("Uploaded %.0f bytes\n", ul); } } diff --git a/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD_T.md b/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD_T.md index 939d66887a33..e75a9809acd1 100644 --- a/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD_T.md +++ b/docs/libcurl/opts/CURLINFO_SIZE_UPLOAD_T.md @@ -16,7 +16,7 @@ Added-in: 7.55.0 # NAME -CURLINFO_SIZE_UPLOAD_T - get the number of uploaded bytes +CURLINFO_SIZE_UPLOAD_T - number of uploaded bytes # SYNOPSIS @@ -41,16 +41,16 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); /* Perform the request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { curl_off_t ul; - res = curl_easy_getinfo(curl, CURLINFO_SIZE_UPLOAD_T, &ul); - if(!res) { + result = curl_easy_getinfo(curl, CURLINFO_SIZE_UPLOAD_T, &ul); + if(!result) { printf("Uploaded %" CURL_FORMAT_CURL_OFF_T " bytes\n", ul); } } diff --git a/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD.md b/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD.md index 53169e03fb9e..c37155686ad2 100644 --- a/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD.md +++ b/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD.md @@ -16,7 +16,7 @@ Added-in: 7.4.1 # NAME -CURLINFO_SPEED_DOWNLOAD - get download speed +CURLINFO_SPEED_DOWNLOAD - download speed # SYNOPSIS @@ -44,16 +44,16 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); /* Perform the request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { double speed; - res = curl_easy_getinfo(curl, CURLINFO_SPEED_DOWNLOAD, &speed); - if(!res) { + result = curl_easy_getinfo(curl, CURLINFO_SPEED_DOWNLOAD, &speed); + if(!result) { printf("Download speed %.0f bytes/sec\n", speed); } } diff --git a/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD_T.md b/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD_T.md index 60d759f84454..3c97fbd5c2ce 100644 --- a/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD_T.md +++ b/docs/libcurl/opts/CURLINFO_SPEED_DOWNLOAD_T.md @@ -16,7 +16,7 @@ Added-in: 7.55.0 # NAME -CURLINFO_SPEED_DOWNLOAD_T - get download speed +CURLINFO_SPEED_DOWNLOAD_T - download speed # SYNOPSIS @@ -41,16 +41,16 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); /* Perform the request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { curl_off_t speed; - res = curl_easy_getinfo(curl, CURLINFO_SPEED_DOWNLOAD_T, &speed); - if(!res) { + result = curl_easy_getinfo(curl, CURLINFO_SPEED_DOWNLOAD_T, &speed); + if(!result) { printf("Download speed %" CURL_FORMAT_CURL_OFF_T " bytes/sec\n", speed); } diff --git a/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD.md b/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD.md index a10b475b60bd..801fe83f048c 100644 --- a/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD.md +++ b/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD.md @@ -15,7 +15,7 @@ Added-in: 7.4.1 # NAME -CURLINFO_SPEED_UPLOAD - get upload speed +CURLINFO_SPEED_UPLOAD - upload speed # SYNOPSIS @@ -42,16 +42,16 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); /* Perform the request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { double speed; - res = curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &speed); - if(!res) { + result = curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &speed); + if(!result) { printf("Upload speed %.0f bytes/sec\n", speed); } } diff --git a/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD_T.md b/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD_T.md index 9f152131b21a..49e126bb4592 100644 --- a/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD_T.md +++ b/docs/libcurl/opts/CURLINFO_SPEED_UPLOAD_T.md @@ -15,7 +15,7 @@ Added-in: 7.55.0 # NAME -CURLINFO_SPEED_UPLOAD_T - get upload speed +CURLINFO_SPEED_UPLOAD_T - upload speed # SYNOPSIS @@ -40,16 +40,16 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); /* Perform the request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { curl_off_t speed; - res = curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD_T, &speed); - if(!res) { + result = curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD_T, &speed); + if(!result) { printf("Upload speed %" CURL_FORMAT_CURL_OFF_T " bytes/sec\n", speed); } } diff --git a/docs/libcurl/opts/CURLINFO_SSL_ENGINES.md b/docs/libcurl/opts/CURLINFO_SSL_ENGINES.md index 6c25f90161b1..da9582c01c29 100644 --- a/docs/libcurl/opts/CURLINFO_SSL_ENGINES.md +++ b/docs/libcurl/opts/CURLINFO_SSL_ENGINES.md @@ -17,7 +17,7 @@ Added-in: 7.12.3 # NAME -CURLINFO_SSL_ENGINES - get an slist of OpenSSL crypto-engines +CURLINFO_SSL_ENGINES - an slist of OpenSSL crypto-engines # SYNOPSIS @@ -46,10 +46,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; struct curl_slist *engines; - res = curl_easy_getinfo(curl, CURLINFO_SSL_ENGINES, &engines); - if((res == CURLE_OK) && engines) { + result = curl_easy_getinfo(curl, CURLINFO_SSL_ENGINES, &engines); + if((result == CURLE_OK) && engines) { /* we have a list, free it when done using it */ curl_slist_free_all(engines); } diff --git a/docs/libcurl/opts/CURLINFO_SSL_VERIFYRESULT.md b/docs/libcurl/opts/CURLINFO_SSL_VERIFYRESULT.md index 15f9495d809f..d4e565b6923b 100644 --- a/docs/libcurl/opts/CURLINFO_SSL_VERIFYRESULT.md +++ b/docs/libcurl/opts/CURLINFO_SSL_VERIFYRESULT.md @@ -18,7 +18,7 @@ Added-in: 7.5 # NAME -CURLINFO_SSL_VERIFYRESULT - get the result of the certificate verification +CURLINFO_SSL_VERIFYRESULT - result of the certificate verification # SYNOPSIS @@ -46,21 +46,21 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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)); + result = curl_easy_perform(curl); + if(result) { + printf("error: %s\n", curl_easy_strerror(result)); curl_easy_cleanup(curl); return 1; } - res = curl_easy_getinfo(curl, CURLINFO_SSL_VERIFYRESULT, - &verifyresult); - if(!res) { + result = curl_easy_getinfo(curl, CURLINFO_SSL_VERIFYRESULT, + &verifyresult); + if(!result) { printf("The peer verification said %s\n", (verifyresult ? "bad" : "fine")); } diff --git a/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME.md b/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME.md index 749930ce46fc..9c5f20ace504 100644 --- a/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME.md +++ b/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME.md @@ -16,7 +16,7 @@ Added-in: 7.9.2 # NAME -CURLINFO_STARTTRANSFER_TIME - get the time until the first byte is received +CURLINFO_STARTTRANSFER_TIME - time to first byte received # SYNOPSIS @@ -47,13 +47,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(CURLE_OK == result) { + result = curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME, &start); + if(CURLE_OK == result) { printf("Time: %.1f", start); } } diff --git a/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME_T.md b/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME_T.md index 2c0d0eac8c2e..79d91ea8d814 100644 --- a/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME_T.md +++ b/docs/libcurl/opts/CURLINFO_STARTTRANSFER_TIME_T.md @@ -16,7 +16,7 @@ Added-in: 7.61.0 # NAME -CURLINFO_STARTTRANSFER_TIME_T - get the time until the first byte is received +CURLINFO_STARTTRANSFER_TIME_T - time to first byte received # SYNOPSIS @@ -48,13 +48,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(CURLE_OK == result) { + result = curl_easy_getinfo(curl, CURLINFO_STARTTRANSFER_TIME_T, &start); + if(CURLE_OK == result) { printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld", start / 1000000, (long)(start % 1000000)); } diff --git a/docs/libcurl/opts/CURLINFO_TLS_SESSION.md b/docs/libcurl/opts/CURLINFO_TLS_SESSION.md index f4209b45b6b0..f4e24253b7a7 100644 --- a/docs/libcurl/opts/CURLINFO_TLS_SESSION.md +++ b/docs/libcurl/opts/CURLINFO_TLS_SESSION.md @@ -18,7 +18,7 @@ Added-in: 7.34.0 # NAME -CURLINFO_TLS_SESSION - get TLS session info +CURLINFO_TLS_SESSION - TLS session info # SYNOPSIS @@ -68,12 +68,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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)); + result = curl_easy_perform(curl); + if(result) + printf("error: %s\n", curl_easy_strerror(result)); curl_easy_getinfo(curl, CURLINFO_TLS_SESSION, &tls); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLINFO_TLS_SSL_PTR.md b/docs/libcurl/opts/CURLINFO_TLS_SSL_PTR.md index 2f87b1a9cdd6..db1a41325bbe 100644 --- a/docs/libcurl/opts/CURLINFO_TLS_SSL_PTR.md +++ b/docs/libcurl/opts/CURLINFO_TLS_SSL_PTR.md @@ -21,7 +21,7 @@ Added-in: 7.48.0 # NAME -CURLINFO_TLS_SESSION, CURLINFO_TLS_SSL_PTR - get TLS session info +CURLINFO_TLS_SSL_PTR - TLS session info # SYNOPSIS @@ -30,12 +30,6 @@ CURLINFO_TLS_SESSION, CURLINFO_TLS_SSL_PTR - get TLS session info 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 @@ -139,8 +133,8 @@ 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) { + CURLcode result = curl_easy_getinfo(curl, CURLINFO_TLS_SSL_PTR, &info); + if(info && !result) { if(CURLSSLBACKEND_OPENSSL == info->backend) { printf("OpenSSL ver. %s\n", SSL_get_version((SSL*)info->internals)); } @@ -150,15 +144,15 @@ static size_t wf(void *ptr, size_t size, size_t nmemb, void *stream) int main(int argc, char **argv) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } - return res; + return result; } ~~~ diff --git a/docs/libcurl/opts/CURLINFO_TOTAL_TIME.md b/docs/libcurl/opts/CURLINFO_TOTAL_TIME.md index 201c4e482349..3cdcee36bbdd 100644 --- a/docs/libcurl/opts/CURLINFO_TOTAL_TIME.md +++ b/docs/libcurl/opts/CURLINFO_TOTAL_TIME.md @@ -16,7 +16,7 @@ Added-in: 7.4.1 # NAME -CURLINFO_TOTAL_TIME - get total time of previous transfer +CURLINFO_TOTAL_TIME - total time of previous transfer # SYNOPSIS @@ -45,13 +45,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(CURLE_OK == result) { + result = curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &total); + if(CURLE_OK == result) { printf("Time: %.1f", total); } } diff --git a/docs/libcurl/opts/CURLINFO_TOTAL_TIME_T.md b/docs/libcurl/opts/CURLINFO_TOTAL_TIME_T.md index 8ae305d5af0d..93c876ad335f 100644 --- a/docs/libcurl/opts/CURLINFO_TOTAL_TIME_T.md +++ b/docs/libcurl/opts/CURLINFO_TOTAL_TIME_T.md @@ -15,7 +15,7 @@ Added-in: 7.61.0 --- # NAME -CURLINFO_TOTAL_TIME_T - get total time of previous transfer in microseconds +CURLINFO_TOTAL_TIME_T - total time of previous transfer # SYNOPSIS @@ -45,13 +45,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(CURLE_OK == result) { + result = curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME_T, &total); + if(CURLE_OK == result) { printf("Time: %" CURL_FORMAT_CURL_OFF_T ".%06ld", total / 1000000, (long)(total % 1000000)); } diff --git a/docs/libcurl/opts/CURLINFO_USED_PROXY.md b/docs/libcurl/opts/CURLINFO_USED_PROXY.md index 01ef3610db0e..11f367ffa40c 100644 --- a/docs/libcurl/opts/CURLINFO_USED_PROXY.md +++ b/docs/libcurl/opts/CURLINFO_USED_PROXY.md @@ -41,19 +41,19 @@ int main(int argc, char *argv[]) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, argv[1]); curl_easy_setopt(curl, CURLOPT_PROXY, "http://127.0.0.1:80"); curl_easy_setopt(curl, CURLOPT_NOPROXY, "example.com"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { /* extract the available proxy authentication types */ long used; - res = curl_easy_getinfo(curl, CURLINFO_USED_PROXY, &used); - if(!res) { - printf("The proxy was %sused\n", used ? "": "NOT "); + result = curl_easy_getinfo(curl, CURLINFO_USED_PROXY, &used); + if(!result) { + printf("The proxy was %sused\n", used ? "" : "NOT "); } } curl_easy_cleanup(curl); diff --git a/docs/libcurl/opts/CURLINFO_XFER_ID.md b/docs/libcurl/opts/CURLINFO_XFER_ID.md index a5f3dd01e761..c01ccd272264 100644 --- a/docs/libcurl/opts/CURLINFO_XFER_ID.md +++ b/docs/libcurl/opts/CURLINFO_XFER_ID.md @@ -15,7 +15,7 @@ Added-in: 8.2.0 # NAME -CURLINFO_XFER_ID - get the ID of a transfer +CURLINFO_XFER_ID - ID of the transfer # SYNOPSIS @@ -45,16 +45,16 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); /* Perform the request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { curl_off_t xfer_id; - res = curl_easy_getinfo(curl, CURLINFO_XFER_ID, &xfer_id); - if(!res) { + result = curl_easy_getinfo(curl, CURLINFO_XFER_ID, &xfer_id); + if(!result) { printf("Transfer ID: %" CURL_FORMAT_CURL_OFF_T "\n", xfer_id); } } diff --git a/docs/libcurl/opts/CURLMOPT_SOCKETFUNCTION.md b/docs/libcurl/opts/CURLMOPT_SOCKETFUNCTION.md index fae15d58a2a9..411b856e9328 100644 --- a/docs/libcurl/opts/CURLMOPT_SOCKETFUNCTION.md +++ b/docs/libcurl/opts/CURLMOPT_SOCKETFUNCTION.md @@ -109,7 +109,7 @@ struct priv { static int sock_cb(CURL *e, curl_socket_t s, int what, void *cbp, void *sockp) { - struct priv *p = sockp; + struct priv *p = cbp; printf("our ptr: %p\n", p->ours); if(what == CURL_POLL_REMOVE) { diff --git a/docs/libcurl/opts/CURLOPT_ACCEPT_ENCODING.md b/docs/libcurl/opts/CURLOPT_ACCEPT_ENCODING.md index 05e7d19a3500..6594061504cb 100644 --- a/docs/libcurl/opts/CURLOPT_ACCEPT_ENCODING.md +++ b/docs/libcurl/opts/CURLOPT_ACCEPT_ENCODING.md @@ -56,18 +56,19 @@ 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. +Setting this option is a request, not an order; the server may or may not do +it. It must be set (to any non-NULL value) or else any 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 Content-Length: header field 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. @@ -75,6 +76,9 @@ option. Using this option multiple times makes the last set string override the previous ones. +**WARNING**: when decompressing data, even tiny transfers might be expanded +and generate a huge amount of bytes. + # HISTORY This option was called CURLOPT_ENCODING before 7.21.6 diff --git a/docs/libcurl/opts/CURLOPT_ADDRESS_SCOPE.md b/docs/libcurl/opts/CURLOPT_ADDRESS_SCOPE.md index 38fa9542b37f..e2880478fb80 100644 --- a/docs/libcurl/opts/CURLOPT_ADDRESS_SCOPE.md +++ b/docs/libcurl/opts/CURLOPT_ADDRESS_SCOPE.md @@ -43,12 +43,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_ALTSVC.md b/docs/libcurl/opts/CURLOPT_ALTSVC.md index b74565790cdd..0b2a9cad7232 100644 --- a/docs/libcurl/opts/CURLOPT_ALTSVC.md +++ b/docs/libcurl/opts/CURLOPT_ALTSVC.md @@ -47,6 +47,10 @@ libcurl cannot fully protect against attacks where an attacker has write access to the same directory where it is directed to save files. This is particularly sensitive if you save files using elevated privileges. +libcurl creates the file to store the alt-svc cache in using default file +permissions, meaning that on *nix systems you may need to restrict your umask +to prevent other users on the same system to access the file. + # DEFAULT NULL. The alt-svc cache is not read nor written to file. diff --git a/docs/libcurl/opts/CURLOPT_AUTOREFERER.md b/docs/libcurl/opts/CURLOPT_AUTOREFERER.md index 0d4918a4daaa..8bc75d46667d 100644 --- a/docs/libcurl/opts/CURLOPT_AUTOREFERER.md +++ b/docs/libcurl/opts/CURLOPT_AUTOREFERER.md @@ -53,7 +53,7 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin"); /* follow redirects */ @@ -62,7 +62,7 @@ int main(void) /* set Referer: automatically when following redirects */ curl_easy_setopt(curl, CURLOPT_AUTOREFERER, 1L); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_BUFFERSIZE.md b/docs/libcurl/opts/CURLOPT_BUFFERSIZE.md index 62212e88f795..a08cd8be185a 100644 --- a/docs/libcurl/opts/CURLOPT_BUFFERSIZE.md +++ b/docs/libcurl/opts/CURLOPT_BUFFERSIZE.md @@ -63,13 +63,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_CAINFO_BLOB.md b/docs/libcurl/opts/CURLOPT_CAINFO_BLOB.md index 149c9b795f61..ffced772b4d8 100644 --- a/docs/libcurl/opts/CURLOPT_CAINFO_BLOB.md +++ b/docs/libcurl/opts/CURLOPT_CAINFO_BLOB.md @@ -13,8 +13,9 @@ See-also: - CURLOPT_SSL_VERIFYPEER (3) TLS-backend: - OpenSSL + - GnuTLS - mbedTLS - - rustls + - Rustls - wolfSSL - Schannel Added-in: 7.77.0 @@ -64,14 +65,14 @@ int main(void) char *strpem = "PEMDATA"; /* strpem must point to a PEM string */ CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } @@ -80,7 +81,7 @@ int main(void) # HISTORY This option is supported by the mbedTLS (since 7.81.0), Rustls (since 7.82.0), -wolfSSL (since 8.2.0), OpenSSL and Schannel backends. +wolfSSL (since 8.2.0), GnuTLS (since 8.18.0), OpenSSL and Schannel backends. # %AVAILABILITY% diff --git a/docs/libcurl/opts/CURLOPT_CAPATH.md b/docs/libcurl/opts/CURLOPT_CAPATH.md index 3dcba2d0a3e8..b82b40fe8ee1 100644 --- a/docs/libcurl/opts/CURLOPT_CAPATH.md +++ b/docs/libcurl/opts/CURLOPT_CAPATH.md @@ -63,10 +63,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); curl_easy_setopt(curl, CURLOPT_CAPATH, "/etc/cert-dir"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_CERTINFO.md b/docs/libcurl/opts/CURLOPT_CERTINFO.md index 7c6641a9fd3e..e3bf6be8c4a2 100644 --- a/docs/libcurl/opts/CURLOPT_CERTINFO.md +++ b/docs/libcurl/opts/CURLOPT_CERTINFO.md @@ -16,7 +16,7 @@ TLS-backend: - OpenSSL - GnuTLS - Schannel - - rustls + - Rustls Added-in: 7.19.1 --- @@ -53,7 +53,7 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://www.example.com/"); /* connect to any HTTPS site, trusted or not */ @@ -62,13 +62,13 @@ int main(void) curl_easy_setopt(curl, CURLOPT_CERTINFO, 1L); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); - if(!res) { + if(!result) { struct curl_certinfo *ci; - res = curl_easy_getinfo(curl, CURLINFO_CERTINFO, &ci); + result = curl_easy_getinfo(curl, CURLINFO_CERTINFO, &ci); - if(!res) { + if(!result) { int i; printf("%d certs!\n", ci->num_of_certs); diff --git a/docs/libcurl/opts/CURLOPT_CONNECT_ONLY.md b/docs/libcurl/opts/CURLOPT_CONNECT_ONLY.md index 0515a8ae35ca..765e0de2323a 100644 --- a/docs/libcurl/opts/CURLOPT_CONNECT_ONLY.md +++ b/docs/libcurl/opts/CURLOPT_CONNECT_ONLY.md @@ -65,11 +65,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(result == CURLE_OK) { /* only connected */ } } diff --git a/docs/libcurl/opts/CURLOPT_COOKIEFILE.md b/docs/libcurl/opts/CURLOPT_COOKIEFILE.md index a4baf8febf46..330f3d57d450 100644 --- a/docs/libcurl/opts/CURLOPT_COOKIEFILE.md +++ b/docs/libcurl/opts/CURLOPT_COOKIEFILE.md @@ -78,13 +78,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_COOKIEJAR.md b/docs/libcurl/opts/CURLOPT_COOKIEJAR.md index 646972792efe..ac3a7074d0a2 100644 --- a/docs/libcurl/opts/CURLOPT_COOKIEJAR.md +++ b/docs/libcurl/opts/CURLOPT_COOKIEJAR.md @@ -58,6 +58,10 @@ libcurl cannot fully protect against attacks where an attacker has write access to the same directory where it is directed to save files. This is particularly sensitive if you save files using elevated privileges. +libcurl creates the file to store cookies using default file permissions, +meaning that on *nix systems you may need to restrict your umask to prevent +other users on the same system to access the file. + # DEFAULT NULL @@ -71,13 +75,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); /* close the handle, write the cookies */ curl_easy_cleanup(curl); diff --git a/docs/libcurl/opts/CURLOPT_COOKIELIST.md b/docs/libcurl/opts/CURLOPT_COOKIELIST.md index a2c43d8dfe2d..5124a53e64b6 100644 --- a/docs/libcurl/opts/CURLOPT_COOKIELIST.md +++ b/docs/libcurl/opts/CURLOPT_COOKIELIST.md @@ -77,7 +77,7 @@ NULL ~~~c /* an inline import of a cookie in Netscape format. */ -#define SEP "\t" /* Tab separates the fields */ +#define SEP "\t" /* Tab separates the fields */ int main(void) { diff --git a/docs/libcurl/opts/CURLOPT_COOKIESESSION.md b/docs/libcurl/opts/CURLOPT_COOKIESESSION.md index bda715af9214..920b4b59fe0b 100644 --- a/docs/libcurl/opts/CURLOPT_COOKIESESSION.md +++ b/docs/libcurl/opts/CURLOPT_COOKIESESSION.md @@ -51,7 +51,7 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin"); /* new "session", do not load session cookies */ @@ -60,7 +60,7 @@ int main(void) /* get the (non session) cookies from this file */ curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "/tmp/cookies.txt"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_COPYPOSTFIELDS.md b/docs/libcurl/opts/CURLOPT_COPYPOSTFIELDS.md index de3dd1b70b03..837fd2de1aaa 100644 --- a/docs/libcurl/opts/CURLOPT_COPYPOSTFIELDS.md +++ b/docs/libcurl/opts/CURLOPT_COPYPOSTFIELDS.md @@ -11,6 +11,8 @@ See-also: - CURLOPT_UPLOAD (3) Protocol: - HTTP + - MQTT + - RTSP Added-in: 7.17.1 --- diff --git a/docs/libcurl/opts/CURLOPT_CRLF.md b/docs/libcurl/opts/CURLOPT_CRLF.md index 275f8bad3cef..4ce1a165c1f4 100644 --- a/docs/libcurl/opts/CURLOPT_CRLF.md +++ b/docs/libcurl/opts/CURLOPT_CRLF.md @@ -45,10 +45,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/"); curl_easy_setopt(curl, CURLOPT_CRLF, 1L); - ret = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_CRLFILE.md b/docs/libcurl/opts/CURLOPT_CRLFILE.md index d5452db19bdc..62f565109090 100644 --- a/docs/libcurl/opts/CURLOPT_CRLFILE.md +++ b/docs/libcurl/opts/CURLOPT_CRLFILE.md @@ -14,7 +14,7 @@ TLS-backend: - GnuTLS - mbedTLS - OpenSSL - - rustls + - Rustls Added-in: 7.19.0 --- @@ -72,10 +72,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); curl_easy_setopt(curl, CURLOPT_CRLFILE, "/etc/certs/crl.pem"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_CURLU.md b/docs/libcurl/opts/CURLOPT_CURLU.md index 737e746a1592..f9207b85db48 100644 --- a/docs/libcurl/opts/CURLOPT_CURLU.md +++ b/docs/libcurl/opts/CURLOPT_CURLU.md @@ -57,13 +57,13 @@ int main(void) CURL *curl = curl_easy_init(); CURLU *urlp = curl_url(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_url_cleanup(urlp); curl_easy_cleanup(curl); diff --git a/docs/libcurl/opts/CURLOPT_CUSTOMREQUEST.md b/docs/libcurl/opts/CURLOPT_CUSTOMREQUEST.md index 060cfd9c777a..9928eef9d64a 100644 --- a/docs/libcurl/opts/CURLOPT_CUSTOMREQUEST.md +++ b/docs/libcurl/opts/CURLOPT_CUSTOMREQUEST.md @@ -119,13 +119,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_DEBUGDATA.md b/docs/libcurl/opts/CURLOPT_DEBUGDATA.md index ed84a27d1235..d15a5576fb53 100644 --- a/docs/libcurl/opts/CURLOPT_DEBUGDATA.md +++ b/docs/libcurl/opts/CURLOPT_DEBUGDATA.md @@ -57,7 +57,7 @@ static int my_trace(CURL *handle, curl_infotype type, int main(void) { CURL *curl; - CURLcode res; + CURLcode result; struct data my_tracedata; curl = curl_easy_init(); @@ -70,7 +70,7 @@ int main(void) curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* always cleanup */ curl_easy_cleanup(curl); diff --git a/docs/libcurl/opts/CURLOPT_DEBUGFUNCTION.md b/docs/libcurl/opts/CURLOPT_DEBUGFUNCTION.md index 4ecfb5327b0f..af1dbd34efc6 100644 --- a/docs/libcurl/opts/CURLOPT_DEBUGFUNCTION.md +++ b/docs/libcurl/opts/CURLOPT_DEBUGFUNCTION.md @@ -186,7 +186,7 @@ int my_trace(CURL *handle, curl_infotype type, int main(void) { CURL *curl; - CURLcode res; + CURLcode result; curl = curl_easy_init(); if(curl) { @@ -199,11 +199,11 @@ int main(void) curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* Check for errors */ - if(res != CURLE_OK) + if(result != CURLE_OK) fprintf(stderr, "curl_easy_perform() failed: %s\n", - curl_easy_strerror(res)); + curl_easy_strerror(result)); /* always cleanup */ curl_easy_cleanup(curl); diff --git a/docs/libcurl/opts/CURLOPT_DIRLISTONLY.md b/docs/libcurl/opts/CURLOPT_DIRLISTONLY.md index d249fa6223f2..548d1f0bf6ee 100644 --- a/docs/libcurl/opts/CURLOPT_DIRLISTONLY.md +++ b/docs/libcurl/opts/CURLOPT_DIRLISTONLY.md @@ -63,13 +63,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/dir/"); /* list only */ curl_easy_setopt(curl, CURLOPT_DIRLISTONLY, 1L); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_DNS_CACHE_TIMEOUT.md b/docs/libcurl/opts/CURLOPT_DNS_CACHE_TIMEOUT.md index 4c40980cdb9f..5a9b7bbb9af8 100644 --- a/docs/libcurl/opts/CURLOPT_DNS_CACHE_TIMEOUT.md +++ b/docs/libcurl/opts/CURLOPT_DNS_CACHE_TIMEOUT.md @@ -68,17 +68,17 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_DNS_INTERFACE.md b/docs/libcurl/opts/CURLOPT_DNS_INTERFACE.md index 015a77c23674..729223d21b62 100644 --- a/docs/libcurl/opts/CURLOPT_DNS_INTERFACE.md +++ b/docs/libcurl/opts/CURLOPT_DNS_INTERFACE.md @@ -52,10 +52,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin"); curl_easy_setopt(curl, CURLOPT_DNS_INTERFACE, "eth0"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP4.md b/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP4.md index f149475c4f87..4613ff3e1d6f 100644 --- a/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP4.md +++ b/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP4.md @@ -51,10 +51,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP6.md b/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP6.md index a0762b78abeb..3a0fe9abe3bb 100644 --- a/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP6.md +++ b/docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP6.md @@ -51,10 +51,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_DNS_SERVERS.md b/docs/libcurl/opts/CURLOPT_DNS_SERVERS.md index a731b966ed18..738714786ff3 100644 --- a/docs/libcurl/opts/CURLOPT_DNS_SERVERS.md +++ b/docs/libcurl/opts/CURLOPT_DNS_SERVERS.md @@ -55,11 +55,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_DNS_USE_GLOBAL_CACHE.md b/docs/libcurl/opts/CURLOPT_DNS_USE_GLOBAL_CACHE.md index 67fba7914257..05093eb2bdbc 100644 --- a/docs/libcurl/opts/CURLOPT_DNS_USE_GLOBAL_CACHE.md +++ b/docs/libcurl/opts/CURLOPT_DNS_USE_GLOBAL_CACHE.md @@ -49,11 +49,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); - /* switch off the use of a global, thread unsafe, cache */ + /* 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_ECH.md b/docs/libcurl/opts/CURLOPT_ECH.md index 9ac65a73a05d..0cb2d7e4fd75 100644 --- a/docs/libcurl/opts/CURLOPT_ECH.md +++ b/docs/libcurl/opts/CURLOPT_ECH.md @@ -11,7 +11,7 @@ Protocol: TLS-backend: - OpenSSL - wolfSSL - - rustls + - Rustls Added-in: 8.8.0 --- @@ -33,7 +33,7 @@ ECH is only compatible with TLSv1.3. This experimental feature requires a special build of OpenSSL, as ECH is not yet supported in OpenSSL releases. In contrast ECH is supported by the latest -BoringSSL, wolfSSL and rustls-ffi releases. +BoringSSL, wolfSSL and Rustls-ffi releases. There is also a known issue with using wolfSSL which does not support ECH when the HelloRetryRequest mechanism is used. diff --git a/docs/libcurl/opts/CURLOPT_ERRORBUFFER.md b/docs/libcurl/opts/CURLOPT_ERRORBUFFER.md index 61bdab4d8af4..6083662aac48 100644 --- a/docs/libcurl/opts/CURLOPT_ERRORBUFFER.md +++ b/docs/libcurl/opts/CURLOPT_ERRORBUFFER.md @@ -69,7 +69,7 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; char errbuf[CURL_ERROR_SIZE]; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com"); @@ -81,20 +81,20 @@ int main(void) errbuf[0] = 0; /* perform the request */ - res = curl_easy_perform(curl); + result = 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) { + if(result != CURLE_OK) { size_t len = strlen(errbuf); - fprintf(stderr, "\nlibcurl: (%d) ", res); + fprintf(stderr, "\nlibcurl: (%d) ", result); if(len) fprintf(stderr, "%s%s", errbuf, ((errbuf[len - 1] != '\n') ? "\n" : "")); else - fprintf(stderr, "%s\n", curl_easy_strerror(res)); + fprintf(stderr, "%s\n", curl_easy_strerror(result)); } } } diff --git a/docs/libcurl/opts/CURLOPT_FAILONERROR.md b/docs/libcurl/opts/CURLOPT_FAILONERROR.md index 24a3bdb7edb3..29578978fc8f 100644 --- a/docs/libcurl/opts/CURLOPT_FAILONERROR.md +++ b/docs/libcurl/opts/CURLOPT_FAILONERROR.md @@ -55,11 +55,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(result == CURLE_HTTP_RETURNED_ERROR) { /* an HTTP response error problem */ } } diff --git a/docs/libcurl/opts/CURLOPT_FILETIME.md b/docs/libcurl/opts/CURLOPT_FILETIME.md index 65676e13808a..6031fcd7605b 100644 --- a/docs/libcurl/opts/CURLOPT_FILETIME.md +++ b/docs/libcurl/opts/CURLOPT_FILETIME.md @@ -49,15 +49,15 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(CURLE_OK == result) { long filetime; - res = curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime); - if((CURLE_OK == res) && (filetime >= 0)) { + result = curl_easy_getinfo(curl, CURLINFO_FILETIME, &filetime); + if((CURLE_OK == result) && (filetime >= 0)) { time_t file_time = (time_t)filetime; printf("filetime: %s", ctime(&file_time)); } diff --git a/docs/libcurl/opts/CURLOPT_FOLLOWLOCATION.md b/docs/libcurl/opts/CURLOPT_FOLLOWLOCATION.md index f3e3b99bd3aa..f67f85c6f2f4 100644 --- a/docs/libcurl/opts/CURLOPT_FOLLOWLOCATION.md +++ b/docs/libcurl/opts/CURLOPT_FOLLOWLOCATION.md @@ -63,7 +63,7 @@ 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). -By default, libcurl only sends `Authentication:` or explicitly set `Cookie:` +By default, libcurl only sends `Authorization:` or explicitly set `Cookie:` headers to the initial host given in the original URL, to avoid leaking username + password to other sites. CURLOPT_UNRESTRICTED_AUTH(3) is provided to change that behavior. diff --git a/docs/libcurl/opts/CURLOPT_FTPPORT.md b/docs/libcurl/opts/CURLOPT_FTPPORT.md index 59e4419512c5..3570b91033bf 100644 --- a/docs/libcurl/opts/CURLOPT_FTPPORT.md +++ b/docs/libcurl/opts/CURLOPT_FTPPORT.md @@ -80,11 +80,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/old-server/file.txt"); curl_easy_setopt(curl, CURLOPT_FTPPORT, "-"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_FTPSSLAUTH.md b/docs/libcurl/opts/CURLOPT_FTPSSLAUTH.md index a2021f830e96..6360fb390869 100644 --- a/docs/libcurl/opts/CURLOPT_FTPSSLAUTH.md +++ b/docs/libcurl/opts/CURLOPT_FTPSSLAUTH.md @@ -57,12 +57,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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, CURLFTPAUTH_SSL); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_FTP_ACCOUNT.md b/docs/libcurl/opts/CURLOPT_FTP_ACCOUNT.md index 3f60368653fe..97b843696ca3 100644 --- a/docs/libcurl/opts/CURLOPT_FTP_ACCOUNT.md +++ b/docs/libcurl/opts/CURLOPT_FTP_ACCOUNT.md @@ -49,12 +49,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_FTP_ALTERNATIVE_TO_USER.md b/docs/libcurl/opts/CURLOPT_FTP_ALTERNATIVE_TO_USER.md index 88824d08fc84..d8ca86427ccd 100644 --- a/docs/libcurl/opts/CURLOPT_FTP_ALTERNATIVE_TO_USER.md +++ b/docs/libcurl/opts/CURLOPT_FTP_ALTERNATIVE_TO_USER.md @@ -51,10 +51,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_FTP_CREATE_MISSING_DIRS.md b/docs/libcurl/opts/CURLOPT_FTP_CREATE_MISSING_DIRS.md index d775e1b8267c..7b1a766d0852 100644 --- a/docs/libcurl/opts/CURLOPT_FTP_CREATE_MISSING_DIRS.md +++ b/docs/libcurl/opts/CURLOPT_FTP_CREATE_MISSING_DIRS.md @@ -63,13 +63,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/non-existing/new.txt"); curl_easy_setopt(curl, CURLOPT_FTP_CREATE_MISSING_DIRS, CURLFTP_CREATE_DIR_RETRY); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_FTP_FILEMETHOD.md b/docs/libcurl/opts/CURLOPT_FTP_FILEMETHOD.md index 847a491a27b6..dffec993d434 100644 --- a/docs/libcurl/opts/CURLOPT_FTP_FILEMETHOD.md +++ b/docs/libcurl/opts/CURLOPT_FTP_FILEMETHOD.md @@ -66,11 +66,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/1/2/3/4/new.txt"); curl_easy_setopt(curl, CURLOPT_FTP_FILEMETHOD, CURLFTPMETHOD_SINGLECWD); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.md b/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.md index 7116b9536f9f..0f529b25d67a 100644 --- a/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.md +++ b/docs/libcurl/opts/CURLOPT_FTP_SKIP_PASV_IP.md @@ -52,12 +52,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_FTP_SSL_CCC.md b/docs/libcurl/opts/CURLOPT_FTP_SSL_CCC.md index cce1616d41f1..78fc976bee7a 100644 --- a/docs/libcurl/opts/CURLOPT_FTP_SSL_CCC.md +++ b/docs/libcurl/opts/CURLOPT_FTP_SSL_CCC.md @@ -59,12 +59,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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, CURLFTPSSL_CCC_ACTIVE); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_FTP_USE_EPRT.md b/docs/libcurl/opts/CURLOPT_FTP_USE_EPRT.md index 8f2cd8244990..781a2c75de23 100644 --- a/docs/libcurl/opts/CURLOPT_FTP_USE_EPRT.md +++ b/docs/libcurl/opts/CURLOPT_FTP_USE_EPRT.md @@ -51,7 +51,7 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/file.txt"); /* contact us back, aka "active" FTP */ @@ -60,7 +60,7 @@ int main(void) /* FTP the way the neanderthals did it */ curl_easy_setopt(curl, CURLOPT_FTP_USE_EPRT, 0L); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_FTP_USE_EPSV.md b/docs/libcurl/opts/CURLOPT_FTP_USE_EPSV.md index 5bed94573d09..48eb13641dd5 100644 --- a/docs/libcurl/opts/CURLOPT_FTP_USE_EPSV.md +++ b/docs/libcurl/opts/CURLOPT_FTP_USE_EPSV.md @@ -51,14 +51,14 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_FTP_USE_PRET.md b/docs/libcurl/opts/CURLOPT_FTP_USE_PRET.md index 5439f2ca8c58..9a26cf45049b 100644 --- a/docs/libcurl/opts/CURLOPT_FTP_USE_PRET.md +++ b/docs/libcurl/opts/CURLOPT_FTP_USE_PRET.md @@ -44,14 +44,14 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_GSSAPI_DELEGATION.md b/docs/libcurl/opts/CURLOPT_GSSAPI_DELEGATION.md index bedceaabcfb6..2196f2398457 100644 --- a/docs/libcurl/opts/CURLOPT_GSSAPI_DELEGATION.md +++ b/docs/libcurl/opts/CURLOPT_GSSAPI_DELEGATION.md @@ -47,12 +47,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); /* delegate if okayed by policy */ curl_easy_setopt(curl, CURLOPT_GSSAPI_DELEGATION, CURLGSSAPI_DELEGATION_POLICY_FLAG); - ret = curl_easy_perform(curl); + result = curl_easy_perform(curl); } } ~~~ diff --git a/docs/libcurl/opts/CURLOPT_HAPROXYPROTOCOL.md b/docs/libcurl/opts/CURLOPT_HAPROXYPROTOCOL.md index 609d891064cb..77ef0e06f33f 100644 --- a/docs/libcurl/opts/CURLOPT_HAPROXYPROTOCOL.md +++ b/docs/libcurl/opts/CURLOPT_HAPROXYPROTOCOL.md @@ -48,10 +48,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); curl_easy_setopt(curl, CURLOPT_HAPROXYPROTOCOL, 1L); - ret = curl_easy_perform(curl); + result = curl_easy_perform(curl); } } ~~~ diff --git a/docs/libcurl/opts/CURLOPT_HAPROXY_CLIENT_IP.md b/docs/libcurl/opts/CURLOPT_HAPROXY_CLIENT_IP.md index 6250101ee1a0..01b7156d1511 100644 --- a/docs/libcurl/opts/CURLOPT_HAPROXY_CLIENT_IP.md +++ b/docs/libcurl/opts/CURLOPT_HAPROXY_CLIENT_IP.md @@ -40,6 +40,10 @@ previous ones. Set it to NULL to disable its use again. The application does not have to keep the string around after setting this option. +Note that if you want to send a *different* HAProxy client IP in a subsequent +request, you need to make sure that it is done over a fresh connection as +libcurl does not send it again while reusing connections. + # DEFAULT NULL, no HAProxy header is sent @@ -53,10 +57,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; 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); + result = curl_easy_perform(curl); } } ~~~ diff --git a/docs/libcurl/opts/CURLOPT_HEADERFUNCTION.md b/docs/libcurl/opts/CURLOPT_HEADERFUNCTION.md index 8e16b78d5552..060ebf5bddc3 100644 --- a/docs/libcurl/opts/CURLOPT_HEADERFUNCTION.md +++ b/docs/libcurl/opts/CURLOPT_HEADERFUNCTION.md @@ -109,7 +109,7 @@ Nothing. static size_t header_callback(char *buffer, size_t size, size_t nitems, void *userdata) { - /* received header is 'nitems' bytes in 'buffer' NOT ZERO TERMINATED */ + /* received header is 'nitems' bytes in 'buffer' NOT NULL-TERMINATED */ /* 'userdata' is set with CURLOPT_HEADERDATA */ return nitems; } diff --git a/docs/libcurl/opts/CURLOPT_HEADEROPT.md b/docs/libcurl/opts/CURLOPT_HEADEROPT.md index 5695d3e0b71a..88d8194aba5d 100644 --- a/docs/libcurl/opts/CURLOPT_HEADEROPT.md +++ b/docs/libcurl/opts/CURLOPT_HEADEROPT.md @@ -54,7 +54,7 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; struct curl_slist *list; list = curl_slist_append(NULL, "Shoesize: 10"); list = curl_slist_append(list, "Accept:"); @@ -66,7 +66,7 @@ int main(void) 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); + result = curl_easy_perform(curl); curl_slist_free_all(list); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_HSTS.md b/docs/libcurl/opts/CURLOPT_HSTS.md index 79665d0a5c1e..667d15972640 100644 --- a/docs/libcurl/opts/CURLOPT_HSTS.md +++ b/docs/libcurl/opts/CURLOPT_HSTS.md @@ -67,6 +67,10 @@ libcurl cannot fully protect against attacks where an attacker has write access to the same directory where it is directed to save files. This is particularly sensitive if you save files using elevated privileges. +libcurl creates the file to store HSTS data in using default file permissions, +meaning that on *nix systems you may need to restrict your umask to prevent +other users on the same system to access the file. + # %PROTOCOLS% # EXAMPLE diff --git a/docs/libcurl/opts/CURLOPT_HSTSREADFUNCTION.md b/docs/libcurl/opts/CURLOPT_HSTSREADFUNCTION.md index 5d03607fa17a..67129f242d4b 100644 --- a/docs/libcurl/opts/CURLOPT_HSTSREADFUNCTION.md +++ b/docs/libcurl/opts/CURLOPT_HSTSREADFUNCTION.md @@ -85,7 +85,7 @@ int main(void) CURL *curl = curl_easy_init(); if(curl) { struct priv my_stuff; - CURLcode res; + CURLcode result; /* set HSTS read callback */ curl_easy_setopt(curl, CURLOPT_HSTSREADFUNCTION, hsts_cb); @@ -93,7 +93,7 @@ int main(void) /* pass in suitable argument to the callback */ curl_easy_setopt(curl, CURLOPT_HSTSREADDATA, &my_stuff); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); } } ~~~ diff --git a/docs/libcurl/opts/CURLOPT_HSTSWRITEFUNCTION.md b/docs/libcurl/opts/CURLOPT_HSTSWRITEFUNCTION.md index 621268ea52c9..cdbdbe5d2629 100644 --- a/docs/libcurl/opts/CURLOPT_HSTSWRITEFUNCTION.md +++ b/docs/libcurl/opts/CURLOPT_HSTSWRITEFUNCTION.md @@ -89,7 +89,7 @@ int main(void) CURL *curl = curl_easy_init(); if(curl) { struct priv my_stuff; - CURLcode res; + CURLcode result; /* set HSTS read callback */ curl_easy_setopt(curl, CURLOPT_HSTSWRITEFUNCTION, hswr_cb); @@ -97,7 +97,7 @@ int main(void) /* pass in suitable argument to the callback */ curl_easy_setopt(curl, CURLOPT_HSTSWRITEDATA, &my_stuff); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); } } ~~~ diff --git a/docs/libcurl/opts/CURLOPT_HTTP09_ALLOWED.md b/docs/libcurl/opts/CURLOPT_HTTP09_ALLOWED.md index 585faa275aae..400348f4ca39 100644 --- a/docs/libcurl/opts/CURLOPT_HTTP09_ALLOWED.md +++ b/docs/libcurl/opts/CURLOPT_HTTP09_ALLOWED.md @@ -45,10 +45,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); curl_easy_setopt(curl, CURLOPT_HTTP09_ALLOWED, 1L); - ret = curl_easy_perform(curl); + result = curl_easy_perform(curl); } } ~~~ diff --git a/docs/libcurl/opts/CURLOPT_HTTPAUTH.md b/docs/libcurl/opts/CURLOPT_HTTPAUTH.md index b21647eda2aa..f0bdc0f12edb 100644 --- a/docs/libcurl/opts/CURLOPT_HTTPAUTH.md +++ b/docs/libcurl/opts/CURLOPT_HTTPAUTH.md @@ -134,12 +134,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); /* allow whatever auth the server speaks */ curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_easy_setopt(curl, CURLOPT_USERPWD, "james:bond"); - ret = curl_easy_perform(curl); + result = curl_easy_perform(curl); } } ~~~ diff --git a/docs/libcurl/opts/CURLOPT_HTTP_CONTENT_DECODING.md b/docs/libcurl/opts/CURLOPT_HTTP_CONTENT_DECODING.md index 10ca0c51009f..f56e55f18415 100644 --- a/docs/libcurl/opts/CURLOPT_HTTP_CONTENT_DECODING.md +++ b/docs/libcurl/opts/CURLOPT_HTTP_CONTENT_DECODING.md @@ -46,10 +46,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); curl_easy_setopt(curl, CURLOPT_HTTP_CONTENT_DECODING, 0L); - ret = curl_easy_perform(curl); + result = curl_easy_perform(curl); } } ~~~ diff --git a/docs/libcurl/opts/CURLOPT_HTTP_TRANSFER_DECODING.md b/docs/libcurl/opts/CURLOPT_HTTP_TRANSFER_DECODING.md index ea59ad2c16cb..15444a2e966b 100644 --- a/docs/libcurl/opts/CURLOPT_HTTP_TRANSFER_DECODING.md +++ b/docs/libcurl/opts/CURLOPT_HTTP_TRANSFER_DECODING.md @@ -44,10 +44,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); curl_easy_setopt(curl, CURLOPT_HTTP_TRANSFER_DECODING, 0L); - ret = curl_easy_perform(curl); + result = curl_easy_perform(curl); } } ~~~ diff --git a/docs/libcurl/opts/CURLOPT_HTTP_VERSION.md b/docs/libcurl/opts/CURLOPT_HTTP_VERSION.md index 4cabb09f8772..1bc23bf7af7a 100644 --- a/docs/libcurl/opts/CURLOPT_HTTP_VERSION.md +++ b/docs/libcurl/opts/CURLOPT_HTTP_VERSION.md @@ -105,11 +105,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS); - ret = curl_easy_perform(curl); - if(ret == CURLE_HTTP_RETURNED_ERROR) { + result = curl_easy_perform(curl); + if(result == CURLE_HTTP_RETURNED_ERROR) { /* an HTTP response error problem */ } } diff --git a/docs/libcurl/opts/CURLOPT_INTERFACE.md b/docs/libcurl/opts/CURLOPT_INTERFACE.md index d58398383b60..dc966aad19df 100644 --- a/docs/libcurl/opts/CURLOPT_INTERFACE.md +++ b/docs/libcurl/opts/CURLOPT_INTERFACE.md @@ -67,12 +67,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin"); curl_easy_setopt(curl, CURLOPT_INTERFACE, "eth0"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_IPRESOLVE.md b/docs/libcurl/opts/CURLOPT_IPRESOLVE.md index 9d7bee31505b..180546a9dfcc 100644 --- a/docs/libcurl/opts/CURLOPT_IPRESOLVE.md +++ b/docs/libcurl/opts/CURLOPT_IPRESOLVE.md @@ -62,13 +62,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_ISSUERCERT.md b/docs/libcurl/opts/CURLOPT_ISSUERCERT.md index 7b6998040bcb..1e10b1bbb297 100644 --- a/docs/libcurl/opts/CURLOPT_ISSUERCERT.md +++ b/docs/libcurl/opts/CURLOPT_ISSUERCERT.md @@ -65,10 +65,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); curl_easy_setopt(curl, CURLOPT_ISSUERCERT, "/etc/certs/cacert.pem"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_ISSUERCERT_BLOB.md b/docs/libcurl/opts/CURLOPT_ISSUERCERT_BLOB.md index e347f6ca9fa1..c0003536196a 100644 --- a/docs/libcurl/opts/CURLOPT_ISSUERCERT_BLOB.md +++ b/docs/libcurl/opts/CURLOPT_ISSUERCERT_BLOB.md @@ -72,14 +72,14 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_KEEP_SENDING_ON_ERROR.md b/docs/libcurl/opts/CURLOPT_KEEP_SENDING_ON_ERROR.md index 5b43545e0f13..eeb4704dd282 100644 --- a/docs/libcurl/opts/CURLOPT_KEEP_SENDING_ON_ERROR.md +++ b/docs/libcurl/opts/CURLOPT_KEEP_SENDING_ON_ERROR.md @@ -51,11 +51,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; 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); + result = curl_easy_perform(curl); } } ~~~ diff --git a/docs/libcurl/opts/CURLOPT_KEYPASSWD.md b/docs/libcurl/opts/CURLOPT_KEYPASSWD.md index 0b7ded9c70c1..d97a94716436 100644 --- a/docs/libcurl/opts/CURLOPT_KEYPASSWD.md +++ b/docs/libcurl/opts/CURLOPT_KEYPASSWD.md @@ -55,12 +55,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_KRBLEVEL.md b/docs/libcurl/opts/CURLOPT_KRBLEVEL.md index 8dc5de7cee7c..cfc728ccd643 100644 --- a/docs/libcurl/opts/CURLOPT_KRBLEVEL.md +++ b/docs/libcurl/opts/CURLOPT_KRBLEVEL.md @@ -52,10 +52,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/foo.bin"); curl_easy_setopt(curl, CURLOPT_KRBLEVEL, "private"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_LOCALPORT.md b/docs/libcurl/opts/CURLOPT_LOCALPORT.md index ef71d5373bac..806de6e9ac56 100644 --- a/docs/libcurl/opts/CURLOPT_LOCALPORT.md +++ b/docs/libcurl/opts/CURLOPT_LOCALPORT.md @@ -45,12 +45,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_LOCALPORTRANGE.md b/docs/libcurl/opts/CURLOPT_LOCALPORTRANGE.md index a3a33ff1088e..da3ef5ae1fcd 100644 --- a/docs/libcurl/opts/CURLOPT_LOCALPORTRANGE.md +++ b/docs/libcurl/opts/CURLOPT_LOCALPORTRANGE.md @@ -48,12 +48,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_LOGIN_OPTIONS.md b/docs/libcurl/opts/CURLOPT_LOGIN_OPTIONS.md index 9d41a3fa74cc..dfdda91efd48 100644 --- a/docs/libcurl/opts/CURLOPT_LOGIN_OPTIONS.md +++ b/docs/libcurl/opts/CURLOPT_LOGIN_OPTIONS.md @@ -64,10 +64,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "smtp://example.com/"); curl_easy_setopt(curl, CURLOPT_LOGIN_OPTIONS, "AUTH=*"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_LOW_SPEED_LIMIT.md b/docs/libcurl/opts/CURLOPT_LOW_SPEED_LIMIT.md index 97c2654604f6..06d1533e4aac 100644 --- a/docs/libcurl/opts/CURLOPT_LOW_SPEED_LIMIT.md +++ b/docs/libcurl/opts/CURLOPT_LOW_SPEED_LIMIT.md @@ -47,13 +47,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(CURLE_OPERATION_TIMEDOUT == result) { printf("Timeout.\n"); } /* always cleanup */ diff --git a/docs/libcurl/opts/CURLOPT_LOW_SPEED_TIME.md b/docs/libcurl/opts/CURLOPT_LOW_SPEED_TIME.md index d478e753ce9c..6a250efb0355 100644 --- a/docs/libcurl/opts/CURLOPT_LOW_SPEED_TIME.md +++ b/docs/libcurl/opts/CURLOPT_LOW_SPEED_TIME.md @@ -44,13 +44,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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) { + result = curl_easy_perform(curl); + if(CURLE_OPERATION_TIMEDOUT == result) { printf("Timeout.\n"); } /* always cleanup */ diff --git a/docs/libcurl/opts/CURLOPT_MAIL_AUTH.md b/docs/libcurl/opts/CURLOPT_MAIL_AUTH.md index 8643c892e364..13b9acadae53 100644 --- a/docs/libcurl/opts/CURLOPT_MAIL_AUTH.md +++ b/docs/libcurl/opts/CURLOPT_MAIL_AUTH.md @@ -61,10 +61,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "smtp://example.com/"); curl_easy_setopt(curl, CURLOPT_MAIL_AUTH, ""); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_MAIL_FROM.md b/docs/libcurl/opts/CURLOPT_MAIL_FROM.md index aa5656e413e3..fe6968f3687a 100644 --- a/docs/libcurl/opts/CURLOPT_MAIL_FROM.md +++ b/docs/libcurl/opts/CURLOPT_MAIL_FROM.md @@ -57,10 +57,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "smtp://example.com/"); curl_easy_setopt(curl, CURLOPT_MAIL_FROM, "president@example.com"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_MAIL_RCPT.md b/docs/libcurl/opts/CURLOPT_MAIL_RCPT.md index 99ee600f589e..de763edd0799 100644 --- a/docs/libcurl/opts/CURLOPT_MAIL_RCPT.md +++ b/docs/libcurl/opts/CURLOPT_MAIL_RCPT.md @@ -67,14 +67,14 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; struct curl_slist *list; list = curl_slist_append(NULL, "root@localhost"); list = curl_slist_append(list, "person@example.com"); list = curl_slist_append(list, " NOTIFY=SUCCESS"); curl_easy_setopt(curl, CURLOPT_URL, "smtp://example.com/"); curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, list); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_slist_free_all(list); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_MAIL_RCPT_ALLOWFAILS.md b/docs/libcurl/opts/CURLOPT_MAIL_RCPT_ALLOWFAILS.md index eae7c3f51c7e..d87ba09bd7bc 100644 --- a/docs/libcurl/opts/CURLOPT_MAIL_RCPT_ALLOWFAILS.md +++ b/docs/libcurl/opts/CURLOPT_MAIL_RCPT_ALLOWFAILS.md @@ -55,7 +55,7 @@ int main(void) CURL *curl = curl_easy_init(); if(curl) { struct curl_slist *list; - CURLcode res; + CURLcode result; /* Adding one valid and one invalid email address */ list = curl_slist_append(NULL, "person@example.com"); @@ -64,7 +64,7 @@ int main(void) curl_easy_setopt(curl, CURLOPT_URL, "smtp://example.com/"); curl_easy_setopt(curl, CURLOPT_MAIL_RCPT_ALLOWFAILS, 1L); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_slist_free_all(list); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_MAXCONNECTS.md b/docs/libcurl/opts/CURLOPT_MAXCONNECTS.md index 80a4f8b3266a..96df2614a148 100644 --- a/docs/libcurl/opts/CURLOPT_MAXCONNECTS.md +++ b/docs/libcurl/opts/CURLOPT_MAXCONNECTS.md @@ -58,11 +58,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; 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); + result = curl_easy_perform(curl); } } ~~~ diff --git a/docs/libcurl/opts/CURLOPT_MAXFILESIZE.md b/docs/libcurl/opts/CURLOPT_MAXFILESIZE.md index 0dd9d7922ab5..8618758f1b41 100644 --- a/docs/libcurl/opts/CURLOPT_MAXFILESIZE.md +++ b/docs/libcurl/opts/CURLOPT_MAXFILESIZE.md @@ -54,11 +54,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; 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); + result = curl_easy_perform(curl); } } ~~~ diff --git a/docs/libcurl/opts/CURLOPT_MAXFILESIZE_LARGE.md b/docs/libcurl/opts/CURLOPT_MAXFILESIZE_LARGE.md index e58b8195e6c8..3ee91696e44d 100644 --- a/docs/libcurl/opts/CURLOPT_MAXFILESIZE_LARGE.md +++ b/docs/libcurl/opts/CURLOPT_MAXFILESIZE_LARGE.md @@ -55,12 +55,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; 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); + result = curl_easy_perform(curl); } } ~~~ diff --git a/docs/libcurl/opts/CURLOPT_MAX_RECV_SPEED_LARGE.md b/docs/libcurl/opts/CURLOPT_MAX_RECV_SPEED_LARGE.md index 2ad3d49b96e4..9a9117669d62 100644 --- a/docs/libcurl/opts/CURLOPT_MAX_RECV_SPEED_LARGE.md +++ b/docs/libcurl/opts/CURLOPT_MAX_RECV_SPEED_LARGE.md @@ -53,11 +53,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; 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); + result = curl_easy_perform(curl); } } ~~~ diff --git a/docs/libcurl/opts/CURLOPT_MAX_SEND_SPEED_LARGE.md b/docs/libcurl/opts/CURLOPT_MAX_SEND_SPEED_LARGE.md index 545fec9a0d1e..34566ece0ded 100644 --- a/docs/libcurl/opts/CURLOPT_MAX_SEND_SPEED_LARGE.md +++ b/docs/libcurl/opts/CURLOPT_MAX_SEND_SPEED_LARGE.md @@ -54,12 +54,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; 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); + result = curl_easy_perform(curl); } } ~~~ diff --git a/docs/libcurl/opts/CURLOPT_NETRC.md b/docs/libcurl/opts/CURLOPT_NETRC.md index aba4ed2ad9cb..65d87cf88158 100644 --- a/docs/libcurl/opts/CURLOPT_NETRC.md +++ b/docs/libcurl/opts/CURLOPT_NETRC.md @@ -131,10 +131,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/"); curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL); - ret = curl_easy_perform(curl); + result = curl_easy_perform(curl); } } ~~~ diff --git a/docs/libcurl/opts/CURLOPT_NETRC_FILE.md b/docs/libcurl/opts/CURLOPT_NETRC_FILE.md index 8863415910f2..dba6f850070c 100644 --- a/docs/libcurl/opts/CURLOPT_NETRC_FILE.md +++ b/docs/libcurl/opts/CURLOPT_NETRC_FILE.md @@ -51,11 +51,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; 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); + result = curl_easy_perform(curl); } } ~~~ diff --git a/docs/libcurl/opts/CURLOPT_NEW_DIRECTORY_PERMS.md b/docs/libcurl/opts/CURLOPT_NEW_DIRECTORY_PERMS.md index 7c2c13fd0094..cb6731912c72 100644 --- a/docs/libcurl/opts/CURLOPT_NEW_DIRECTORY_PERMS.md +++ b/docs/libcurl/opts/CURLOPT_NEW_DIRECTORY_PERMS.md @@ -48,12 +48,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; 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); + result = curl_easy_perform(curl); } } ~~~ diff --git a/docs/libcurl/opts/CURLOPT_NEW_FILE_PERMS.md b/docs/libcurl/opts/CURLOPT_NEW_FILE_PERMS.md index 7252ac5956b6..4c9579c8264e 100644 --- a/docs/libcurl/opts/CURLOPT_NEW_FILE_PERMS.md +++ b/docs/libcurl/opts/CURLOPT_NEW_FILE_PERMS.md @@ -46,10 +46,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; 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); + result = curl_easy_perform(curl); } } ~~~ diff --git a/docs/libcurl/opts/CURLOPT_NOPROXY.md b/docs/libcurl/opts/CURLOPT_NOPROXY.md index 117cf09be887..40f3d4cc6547 100644 --- a/docs/libcurl/opts/CURLOPT_NOPROXY.md +++ b/docs/libcurl/opts/CURLOPT_NOPROXY.md @@ -76,7 +76,7 @@ int main(void) /* accept various URLs */ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); /* use this proxy */ - curl_easy_setopt(curl, CURLOPT_PROXY, "http://proxy:80"); + curl_easy_setopt(curl, CURLOPT_PROXY, "http://proxy.example:80"); /* ... but make sure this host name is not proxied */ curl_easy_setopt(curl, CURLOPT_NOPROXY, "www.example.com"); curl_easy_perform(curl); diff --git a/docs/libcurl/opts/CURLOPT_NOSIGNAL.md b/docs/libcurl/opts/CURLOPT_NOSIGNAL.md index 27886ff65e75..c89b01465bac 100644 --- a/docs/libcurl/opts/CURLOPT_NOSIGNAL.md +++ b/docs/libcurl/opts/CURLOPT_NOSIGNAL.md @@ -56,12 +56,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_OPENSOCKETDATA.md b/docs/libcurl/opts/CURLOPT_OPENSOCKETDATA.md index d91a7da3ba7f..2bcdee3b6650 100644 --- a/docs/libcurl/opts/CURLOPT_OPENSOCKETDATA.md +++ b/docs/libcurl/opts/CURLOPT_OPENSOCKETDATA.md @@ -63,7 +63,7 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; extern int sockfd; /* the already connected one */ /* libcurl thinks that you connect to the host @@ -76,7 +76,7 @@ int main(void) /* call this function to set options for the socket */ curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_OPENSOCKETFUNCTION.md b/docs/libcurl/opts/CURLOPT_OPENSOCKETFUNCTION.md index 89931d0e066c..35915163589e 100644 --- a/docs/libcurl/opts/CURLOPT_OPENSOCKETFUNCTION.md +++ b/docs/libcurl/opts/CURLOPT_OPENSOCKETFUNCTION.md @@ -111,7 +111,7 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; extern int sockfd; /* the already connected one */ /* libcurl thinks that you connect to the host * and port that you specify in the URL option. */ @@ -123,7 +123,7 @@ int main(void) /* call this function to set options for the socket */ curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_PASSWORD.md b/docs/libcurl/opts/CURLOPT_PASSWORD.md index 26bbf32d39e0..f8b9ee752d9e 100644 --- a/docs/libcurl/opts/CURLOPT_PASSWORD.md +++ b/docs/libcurl/opts/CURLOPT_PASSWORD.md @@ -53,12 +53,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin"); curl_easy_setopt(curl, CURLOPT_PASSWORD, "qwerty"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_PORT.md b/docs/libcurl/opts/CURLOPT_PORT.md index e452cb54f72a..c0cf765dbacf 100644 --- a/docs/libcurl/opts/CURLOPT_PORT.md +++ b/docs/libcurl/opts/CURLOPT_PORT.md @@ -55,10 +55,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin"); curl_easy_setopt(curl, CURLOPT_PORT, 8080L); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_POST.md b/docs/libcurl/opts/CURLOPT_POST.md index c7850f3aed1e..1678b50e6bfb 100644 --- a/docs/libcurl/opts/CURLOPT_POST.md +++ b/docs/libcurl/opts/CURLOPT_POST.md @@ -81,13 +81,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE.md b/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE.md index 5871e91d9b30..10414e7eea7b 100644 --- a/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE.md +++ b/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE.md @@ -9,6 +9,8 @@ See-also: - CURLOPT_POSTFIELDSIZE_LARGE (3) Protocol: - HTTP + - MQTT + - RTSP Added-in: 7.2 --- diff --git a/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE_LARGE.md b/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE_LARGE.md index 16e874b667ed..e3d983e25338 100644 --- a/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE_LARGE.md +++ b/docs/libcurl/opts/CURLOPT_POSTFIELDSIZE_LARGE.md @@ -10,6 +10,8 @@ See-also: - CURLOPT_POSTFIELDSIZE (3) Protocol: - HTTP + - MQTT + - RTSP Added-in: 7.11.1 --- diff --git a/docs/libcurl/opts/CURLOPT_POSTQUOTE.md b/docs/libcurl/opts/CURLOPT_POSTQUOTE.md index 0457f490db64..55ef81aabc02 100644 --- a/docs/libcurl/opts/CURLOPT_POSTQUOTE.md +++ b/docs/libcurl/opts/CURLOPT_POSTQUOTE.md @@ -56,13 +56,13 @@ int main(void) CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_PREQUOTE.md b/docs/libcurl/opts/CURLOPT_PREQUOTE.md index c570e57731bd..79cf9fee80e4 100644 --- a/docs/libcurl/opts/CURLOPT_PREQUOTE.md +++ b/docs/libcurl/opts/CURLOPT_PREQUOTE.md @@ -57,13 +57,13 @@ int main(void) CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_PROXY.md b/docs/libcurl/opts/CURLOPT_PROXY.md index 310e123e3db2..2d9d456dba9f 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY.md +++ b/docs/libcurl/opts/CURLOPT_PROXY.md @@ -89,8 +89,9 @@ 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. -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 +Unix domain sockets are supported for SOCKS proxies. Set `localhost` for the +host part and append the absolute path to the domain socket. For example: +`socks5h://localhost/path/to/socket.sock` When you set a hostname to use, do not assume that there is any particular single port number used widely for proxies. Specify it. @@ -137,7 +138,7 @@ 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_setopt(curl, CURLOPT_PROXY, "http://proxy.example:80"); curl_easy_perform(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXYAUTH.md b/docs/libcurl/opts/CURLOPT_PROXYAUTH.md index c010c8fd0ccb..459fd429c371 100644 --- a/docs/libcurl/opts/CURLOPT_PROXYAUTH.md +++ b/docs/libcurl/opts/CURLOPT_PROXYAUTH.md @@ -53,7 +53,7 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); /* use this proxy */ curl_easy_setopt(curl, CURLOPT_PROXY, "http://local.example.com:1080"); @@ -61,7 +61,7 @@ int main(void) 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXYPASSWORD.md b/docs/libcurl/opts/CURLOPT_PROXYPASSWORD.md index 20e3a687a603..c4664b66311e 100644 --- a/docs/libcurl/opts/CURLOPT_PROXYPASSWORD.md +++ b/docs/libcurl/opts/CURLOPT_PROXYPASSWORD.md @@ -53,12 +53,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXYPORT.md b/docs/libcurl/opts/CURLOPT_PROXYPORT.md index 31abbf9cbfb7..6a390ae9030e 100644 --- a/docs/libcurl/opts/CURLOPT_PROXYPORT.md +++ b/docs/libcurl/opts/CURLOPT_PROXYPORT.md @@ -54,11 +54,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXYTYPE.md b/docs/libcurl/opts/CURLOPT_PROXYTYPE.md index d7870efc5713..6000d10b00bc 100644 --- a/docs/libcurl/opts/CURLOPT_PROXYTYPE.md +++ b/docs/libcurl/opts/CURLOPT_PROXYTYPE.md @@ -81,12 +81,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXYUSERNAME.md b/docs/libcurl/opts/CURLOPT_PROXYUSERNAME.md index 0bf170f4e899..be196eed1336 100644 --- a/docs/libcurl/opts/CURLOPT_PROXYUSERNAME.md +++ b/docs/libcurl/opts/CURLOPT_PROXYUSERNAME.md @@ -53,12 +53,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXYUSERPWD.md b/docs/libcurl/opts/CURLOPT_PROXYUSERPWD.md index 3fed4a3d5557..87dac82a13f2 100644 --- a/docs/libcurl/opts/CURLOPT_PROXYUSERPWD.md +++ b/docs/libcurl/opts/CURLOPT_PROXYUSERPWD.md @@ -55,11 +55,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXY_CAINFO.md b/docs/libcurl/opts/CURLOPT_PROXY_CAINFO.md index 6be10774db83..3eb5af912ac2 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_CAINFO.md +++ b/docs/libcurl/opts/CURLOPT_PROXY_CAINFO.md @@ -69,12 +69,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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, "https://proxy.example:443"); curl_easy_setopt(curl, CURLOPT_PROXY_CAINFO, "/etc/certs/cabundle.pem"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXY_CAINFO_BLOB.md b/docs/libcurl/opts/CURLOPT_PROXY_CAINFO_BLOB.md index a352886e061f..36666edf212c 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_CAINFO_BLOB.md +++ b/docs/libcurl/opts/CURLOPT_PROXY_CAINFO_BLOB.md @@ -18,7 +18,7 @@ Protocol: - TLS TLS-backend: - OpenSSL - - rustls + - Rustls - Schannel Added-in: 7.77.0 --- @@ -69,16 +69,16 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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"); + curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy.example: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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXY_CAPATH.md b/docs/libcurl/opts/CURLOPT_PROXY_CAPATH.md index d0fce53cae06..0bd3770f9179 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_CAPATH.md +++ b/docs/libcurl/opts/CURLOPT_PROXY_CAPATH.md @@ -61,12 +61,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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, "https://proxy.example:443"); curl_easy_setopt(curl, CURLOPT_PROXY_CAPATH, "/etc/cert-dir"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXY_CRLFILE.md b/docs/libcurl/opts/CURLOPT_PROXY_CRLFILE.md index 76c961251545..2dda8235c686 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_CRLFILE.md +++ b/docs/libcurl/opts/CURLOPT_PROXY_CRLFILE.md @@ -71,11 +71,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT.md b/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT.md index 88af6f8ed9d1..c3687a46fe87 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT.md +++ b/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT.md @@ -67,12 +67,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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, "https://proxy.example:443"); curl_easy_setopt(curl, CURLOPT_PROXY_ISSUERCERT, "/etc/certs/cacert.pem"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT_BLOB.md b/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT_BLOB.md index a6977513974b..180a7b1808bf 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT_BLOB.md +++ b/docs/libcurl/opts/CURLOPT_PROXY_ISSUERCERT_BLOB.md @@ -73,16 +73,16 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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"); + curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy.example: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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXY_KEYPASSWD.md b/docs/libcurl/opts/CURLOPT_PROXY_KEYPASSWD.md index 4d8287095312..98f3683eef2b 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_KEYPASSWD.md +++ b/docs/libcurl/opts/CURLOPT_PROXY_KEYPASSWD.md @@ -59,11 +59,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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, "https://proxy.example:443"); curl_easy_setopt(curl, CURLOPT_PROXY_KEYPASSWD, "superman"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXY_PINNEDPUBLICKEY.md b/docs/libcurl/opts/CURLOPT_PROXY_PINNEDPUBLICKEY.md index 49c28a7b6e6e..70c294c5ac5b 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_PINNEDPUBLICKEY.md +++ b/docs/libcurl/opts/CURLOPT_PROXY_PINNEDPUBLICKEY.md @@ -67,7 +67,7 @@ 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, "https://proxy.example:443"); curl_easy_setopt(curl, CURLOPT_PROXY_PINNEDPUBLICKEY, "sha256//YhKJKSzoTt2b5FP18fvpHo7fJYqQCjA" "a3HWY3tvRMwE=;sha256//t62CeU2tQiqkexU74" diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SERVICE_NAME.md b/docs/libcurl/opts/CURLOPT_PROXY_SERVICE_NAME.md index 59cd1aaea204..9bdb4af26aa3 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_SERVICE_NAME.md +++ b/docs/libcurl/opts/CURLOPT_PROXY_SERVICE_NAME.md @@ -51,10 +51,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); curl_easy_setopt(curl, CURLOPT_PROXY_SERVICE_NAME, "custom"); - ret = curl_easy_perform(curl); + result = curl_easy_perform(curl); } } ~~~ diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT.md b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT.md index f54832839f45..8ba84add1fb0 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT.md +++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT.md @@ -62,13 +62,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); - curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy"); + curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy.example"); 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLCERTTYPE.md b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERTTYPE.md index f616c75e4034..c7c7b728a583 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_SSLCERTTYPE.md +++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERTTYPE.md @@ -58,14 +58,14 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); - curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy"); + curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy.example"); 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT_BLOB.md b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT_BLOB.md index e3b947b14615..5be7b134a0c0 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT_BLOB.md +++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLCERT_BLOB.md @@ -62,17 +62,17 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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, "https://proxy.example"); 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY.md b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY.md index 74b431a6b06e..9b8d29373530 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY.md +++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY.md @@ -62,13 +62,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); - curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy"); + curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy.example"); 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLKEYTYPE.md b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEYTYPE.md index df14f081f5cd..8513dffceda4 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_SSLKEYTYPE.md +++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEYTYPE.md @@ -51,14 +51,14 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); - curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy"); + curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy.example"); 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY_BLOB.md b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY_BLOB.md index 91e91468493d..65f940b8610c 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY_BLOB.md +++ b/docs/libcurl/opts/CURLOPT_PROXY_SSLKEY_BLOB.md @@ -59,10 +59,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; struct curl_blob blob; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); - curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy"); + curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy.example"); blob.data = certificateData; blob.len = filesize; blob.flags = CURL_BLOB_COPY; @@ -73,7 +73,7 @@ int main(void) 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSL_CIPHER_LIST.md b/docs/libcurl/opts/CURLOPT_PROXY_SSL_CIPHER_LIST.md index 239ce03c73dd..ce1f63aa3b97 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_SSL_CIPHER_LIST.md +++ b/docs/libcurl/opts/CURLOPT_PROXY_SSL_CIPHER_LIST.md @@ -17,7 +17,7 @@ TLS-backend: - Schannel - wolfSSL - mbedTLS - - rustls + - Rustls Added-in: 7.52.0 --- @@ -75,13 +75,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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, "ECDHE-ECDSA-CHACHA20-POLY1305:" "ECDHE-RSA-CHACHA20-POLY1305"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.md b/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.md index 18b7ce6b36a1..cbe422b08e92 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.md +++ b/docs/libcurl/opts/CURLOPT_PROXY_SSL_OPTIONS.md @@ -104,13 +104,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); - curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy"); + curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy.example"); /* 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXY_TLS13_CIPHERS.md b/docs/libcurl/opts/CURLOPT_PROXY_TLS13_CIPHERS.md index ee17d27e99c1..999a111c98b9 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_TLS13_CIPHERS.md +++ b/docs/libcurl/opts/CURLOPT_PROXY_TLS13_CIPHERS.md @@ -16,7 +16,7 @@ TLS-backend: - OpenSSL - wolfSSL - mbedTLS - - rustls + - Rustls Added-in: 7.61.0 --- @@ -70,11 +70,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_PASSWORD.md b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_PASSWORD.md index 91f211071641..17acca6761d6 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_PASSWORD.md +++ b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_PASSWORD.md @@ -56,13 +56,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); - curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy"); + curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy.example"); 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_TYPE.md b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_TYPE.md index 4c7cfd700f91..d1badf4be565 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_TYPE.md +++ b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_TYPE.md @@ -63,13 +63,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); - curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy"); + curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy.example"); 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_USERNAME.md b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_USERNAME.md index 44e32299ee04..c4db7aa81526 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_USERNAME.md +++ b/docs/libcurl/opts/CURLOPT_PROXY_TLSAUTH_USERNAME.md @@ -56,13 +56,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); - curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy"); + curl_easy_setopt(curl, CURLOPT_PROXY, "https://proxy.example"); 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_PROXY_TRANSFER_MODE.md b/docs/libcurl/opts/CURLOPT_PROXY_TRANSFER_MODE.md index f424a27ef592..93b483802e66 100644 --- a/docs/libcurl/opts/CURLOPT_PROXY_TRANSFER_MODE.md +++ b/docs/libcurl/opts/CURLOPT_PROXY_TRANSFER_MODE.md @@ -48,13 +48,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_QUICK_EXIT.md b/docs/libcurl/opts/CURLOPT_QUICK_EXIT.md index 7027159e31f9..d6505244cb6a 100644 --- a/docs/libcurl/opts/CURLOPT_QUICK_EXIT.md +++ b/docs/libcurl/opts/CURLOPT_QUICK_EXIT.md @@ -47,9 +47,9 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; curl_easy_setopt(curl, CURLOPT_QUICK_EXIT, 1L); - ret = curl_easy_perform(curl); + result = curl_easy_perform(curl); } } ~~~ diff --git a/docs/libcurl/opts/CURLOPT_QUOTE.md b/docs/libcurl/opts/CURLOPT_QUOTE.md index 11b6997c6811..d4365f7b4185 100644 --- a/docs/libcurl/opts/CURLOPT_QUOTE.md +++ b/docs/libcurl/opts/CURLOPT_QUOTE.md @@ -147,13 +147,13 @@ int main(void) CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_READFUNCTION.md b/docs/libcurl/opts/CURLOPT_READFUNCTION.md index 71ad2e9ca0fd..0046ded635c8 100644 --- a/docs/libcurl/opts/CURLOPT_READFUNCTION.md +++ b/docs/libcurl/opts/CURLOPT_READFUNCTION.md @@ -36,9 +36,8 @@ 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. +the server. The data area pointed at by the pointer *buffer* should be filled +up with at most *nitems* number of bytes by your function. *size* is always 1. Set the *userdata* argument with the CURLOPT_READDATA(3) option. diff --git a/docs/libcurl/opts/CURLOPT_RTSP_CLIENT_CSEQ.md b/docs/libcurl/opts/CURLOPT_RTSP_CLIENT_CSEQ.md index d7b13a04abcb..27da0f3b8319 100644 --- a/docs/libcurl/opts/CURLOPT_RTSP_CLIENT_CSEQ.md +++ b/docs/libcurl/opts/CURLOPT_RTSP_CLIENT_CSEQ.md @@ -45,10 +45,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "rtsp://example.com/"); curl_easy_setopt(curl, CURLOPT_RTSP_CLIENT_CSEQ, 1234L); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_RTSP_REQUEST.md b/docs/libcurl/opts/CURLOPT_RTSP_REQUEST.md index 89e303d4ab1a..e42e75b712f1 100644 --- a/docs/libcurl/opts/CURLOPT_RTSP_REQUEST.md +++ b/docs/libcurl/opts/CURLOPT_RTSP_REQUEST.md @@ -121,11 +121,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_RTSP_SERVER_CSEQ.md b/docs/libcurl/opts/CURLOPT_RTSP_SERVER_CSEQ.md index d054be7a55ec..f8672f1bf4c8 100644 --- a/docs/libcurl/opts/CURLOPT_RTSP_SERVER_CSEQ.md +++ b/docs/libcurl/opts/CURLOPT_RTSP_SERVER_CSEQ.md @@ -44,10 +44,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "rtsp://example.com/"); curl_easy_setopt(curl, CURLOPT_RTSP_SERVER_CSEQ, 1234L); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_RTSP_SESSION_ID.md b/docs/libcurl/opts/CURLOPT_RTSP_SESSION_ID.md index 0d76e60186b0..e60438eecb52 100644 --- a/docs/libcurl/opts/CURLOPT_RTSP_SESSION_ID.md +++ b/docs/libcurl/opts/CURLOPT_RTSP_SESSION_ID.md @@ -52,11 +52,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; char *prev_id = "old"; /* 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_RTSP_STREAM_URI.md b/docs/libcurl/opts/CURLOPT_RTSP_STREAM_URI.md index eb745da04378..619096bf1ad7 100644 --- a/docs/libcurl/opts/CURLOPT_RTSP_STREAM_URI.md +++ b/docs/libcurl/opts/CURLOPT_RTSP_STREAM_URI.md @@ -56,11 +56,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_RTSP_TRANSPORT.md b/docs/libcurl/opts/CURLOPT_RTSP_TRANSPORT.md index cba9b4ad539b..44633cd71dd8 100644 --- a/docs/libcurl/opts/CURLOPT_RTSP_TRANSPORT.md +++ b/docs/libcurl/opts/CURLOPT_RTSP_TRANSPORT.md @@ -48,12 +48,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SASL_AUTHZID.md b/docs/libcurl/opts/CURLOPT_SASL_AUTHZID.md index 7f627f5a615f..e32380d65ed3 100644 --- a/docs/libcurl/opts/CURLOPT_SASL_AUTHZID.md +++ b/docs/libcurl/opts/CURLOPT_SASL_AUTHZID.md @@ -59,12 +59,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SASL_IR.md b/docs/libcurl/opts/CURLOPT_SASL_IR.md index 6a3b50ca35da..c99239db5b7c 100644 --- a/docs/libcurl/opts/CURLOPT_SASL_IR.md +++ b/docs/libcurl/opts/CURLOPT_SASL_IR.md @@ -56,10 +56,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "smtp://example.com/"); curl_easy_setopt(curl, CURLOPT_SASL_IR, 1L); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SERVER_RESPONSE_TIMEOUT.md b/docs/libcurl/opts/CURLOPT_SERVER_RESPONSE_TIMEOUT.md index 30ae25b42ac5..68e27529dc29 100644 --- a/docs/libcurl/opts/CURLOPT_SERVER_RESPONSE_TIMEOUT.md +++ b/docs/libcurl/opts/CURLOPT_SERVER_RESPONSE_TIMEOUT.md @@ -5,6 +5,7 @@ Title: CURLOPT_SERVER_RESPONSE_TIMEOUT Section: 3 Source: libcurl See-also: + - CURLOPT_SERVER_RESPONSE_TIMEOUT_MS (3) - CURLOPT_CONNECTTIMEOUT (3) - CURLOPT_LOW_SPEED_LIMIT (3) - CURLOPT_TIMEOUT (3) @@ -40,11 +41,9 @@ connection is considered dead and the transfer fails. 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 +60 seconds # %PROTOCOLS% @@ -55,17 +54,21 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } ~~~ +# HISTORY + +This option was formerly known as CURLOPT_FTP_RESPONSE_TIMEOUT. + # %AVAILABILITY% # RETURN VALUE diff --git a/docs/libcurl/opts/CURLOPT_SERVER_RESPONSE_TIMEOUT_MS.md b/docs/libcurl/opts/CURLOPT_SERVER_RESPONSE_TIMEOUT_MS.md index 267659cde2db..cb57bf5d4a77 100644 --- a/docs/libcurl/opts/CURLOPT_SERVER_RESPONSE_TIMEOUT_MS.md +++ b/docs/libcurl/opts/CURLOPT_SERVER_RESPONSE_TIMEOUT_MS.md @@ -5,6 +5,7 @@ Title: CURLOPT_SERVER_RESPONSE_TIMEOUT_MS Section: 3 Source: libcurl See-also: + - CURLOPT_SERVER_RESPONSE_TIMEOUT (3) - CURLOPT_CONNECTTIMEOUT (3) - CURLOPT_LOW_SPEED_LIMIT (3) - CURLOPT_TIMEOUT (3) @@ -47,7 +48,7 @@ This is the millisecond version of CURLOPT_SERVER_RESPONSE_TIMEOUT(3). # DEFAULT -None +60000 milliseconds # %PROTOCOLS% @@ -58,11 +59,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_SERVICE_NAME.md b/docs/libcurl/opts/CURLOPT_SERVICE_NAME.md index 56d7029cd255..f6efb393f24e 100644 --- a/docs/libcurl/opts/CURLOPT_SERVICE_NAME.md +++ b/docs/libcurl/opts/CURLOPT_SERVICE_NAME.md @@ -56,10 +56,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode ret; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); curl_easy_setopt(curl, CURLOPT_SERVICE_NAME, "custom"); - ret = curl_easy_perform(curl); + result = curl_easy_perform(curl); } } ~~~ diff --git a/docs/libcurl/opts/CURLOPT_SHARE.md b/docs/libcurl/opts/CURLOPT_SHARE.md index 9b9a281e00be..2c6a496593fd 100644 --- a/docs/libcurl/opts/CURLOPT_SHARE.md +++ b/docs/libcurl/opts/CURLOPT_SHARE.md @@ -57,21 +57,21 @@ int main(void) CURL *curl = curl_easy_init(); CURL *curl2 = curl_easy_init(); /* a second handle */ if(curl) { - CURLcode res; + CURLcode result; 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); + result = 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); + result = curl_easy_perform(curl2); curl_easy_cleanup(curl2); curl_share_cleanup(shobject); diff --git a/docs/libcurl/opts/CURLOPT_SOCKOPTDATA.md b/docs/libcurl/opts/CURLOPT_SOCKOPTDATA.md index dbf75da3bca8..be913df0296b 100644 --- a/docs/libcurl/opts/CURLOPT_SOCKOPTDATA.md +++ b/docs/libcurl/opts/CURLOPT_SOCKOPTDATA.md @@ -51,7 +51,7 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; int recvbuffersize = 256 * 1024; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); @@ -60,7 +60,7 @@ int main(void) curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback); curl_easy_setopt(curl, CURLOPT_SOCKOPTDATA, &recvbuffersize); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_SOCKOPTFUNCTION.md b/docs/libcurl/opts/CURLOPT_SOCKOPTFUNCTION.md index 3467acf77f65..b20a387b1205 100644 --- a/docs/libcurl/opts/CURLOPT_SOCKOPTFUNCTION.md +++ b/docs/libcurl/opts/CURLOPT_SOCKOPTFUNCTION.md @@ -105,7 +105,7 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; int sockfd; /* our custom file descriptor */ /* libcurl thinks that you connect to the host * and port that you specify in the URL option. */ @@ -117,7 +117,7 @@ int main(void) /* call this function to set options for the socket */ curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_SOCKS5_AUTH.md b/docs/libcurl/opts/CURLOPT_SOCKS5_AUTH.md index a9adf6b77d5a..826fc4c1f2b3 100644 --- a/docs/libcurl/opts/CURLOPT_SOCKS5_AUTH.md +++ b/docs/libcurl/opts/CURLOPT_SOCKS5_AUTH.md @@ -35,7 +35,7 @@ password with the CURLOPT_PROXYUSERPWD(3) option. # DEFAULT -CURLAUTH_BASIC|CURLAUTH_GSSAPI +CURLAUTH_BASIC | CURLAUTH_GSSAPI # %PROTOCOLS% diff --git a/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_NEC.md b/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_NEC.md index f873c6a5cc35..38f5004adca9 100644 --- a/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_NEC.md +++ b/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_NEC.md @@ -45,11 +45,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_SERVICE.md b/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_SERVICE.md index b47c2ca2264b..673112cf3233 100644 --- a/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_SERVICE.md +++ b/docs/libcurl/opts/CURLOPT_SOCKS5_GSSAPI_SERVICE.md @@ -49,11 +49,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SSH_AUTH_TYPES.md b/docs/libcurl/opts/CURLOPT_SSH_AUTH_TYPES.md index 60a6025c8c41..3b9fb989d156 100644 --- a/docs/libcurl/opts/CURLOPT_SSH_AUTH_TYPES.md +++ b/docs/libcurl/opts/CURLOPT_SSH_AUTH_TYPES.md @@ -50,11 +50,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_MD5.md b/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_MD5.md index 09810f22ee7f..5dfb2ff1d247 100644 --- a/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_MD5.md +++ b/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_MD5.md @@ -56,11 +56,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256.md b/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256.md index 3e6861bc35d6..e83bf918d79b 100644 --- a/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256.md +++ b/docs/libcurl/opts/CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256.md @@ -52,11 +52,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SSH_KEYFUNCTION.md b/docs/libcurl/opts/CURLOPT_SSH_KEYFUNCTION.md index 1e21b614f136..85801b8af799 100644 --- a/docs/libcurl/opts/CURLOPT_SSH_KEYFUNCTION.md +++ b/docs/libcurl/opts/CURLOPT_SSH_KEYFUNCTION.md @@ -141,7 +141,7 @@ int main(void) curl_easy_setopt(curl, CURLOPT_SSH_KNOWNHOSTS, "/home/user/known_hosts"); curl_easy_perform(curl); -} + } } ~~~ diff --git a/docs/libcurl/opts/CURLOPT_SSH_KNOWNHOSTS.md b/docs/libcurl/opts/CURLOPT_SSH_KNOWNHOSTS.md index e4443a10b6f2..cdd45110afbb 100644 --- a/docs/libcurl/opts/CURLOPT_SSH_KNOWNHOSTS.md +++ b/docs/libcurl/opts/CURLOPT_SSH_KNOWNHOSTS.md @@ -58,11 +58,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SSH_PRIVATE_KEYFILE.md b/docs/libcurl/opts/CURLOPT_SSH_PRIVATE_KEYFILE.md index a92f744d59a3..2a1f79845dbf 100644 --- a/docs/libcurl/opts/CURLOPT_SSH_PRIVATE_KEYFILE.md +++ b/docs/libcurl/opts/CURLOPT_SSH_PRIVATE_KEYFILE.md @@ -57,12 +57,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SSH_PUBLIC_KEYFILE.md b/docs/libcurl/opts/CURLOPT_SSH_PUBLIC_KEYFILE.md index d7878e862640..d7df84fa1bfc 100644 --- a/docs/libcurl/opts/CURLOPT_SSH_PUBLIC_KEYFILE.md +++ b/docs/libcurl/opts/CURLOPT_SSH_PUBLIC_KEYFILE.md @@ -53,11 +53,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SSLCERT.md b/docs/libcurl/opts/CURLOPT_SSLCERT.md index 20e7d1a17649..d3669e90a4e4 100644 --- a/docs/libcurl/opts/CURLOPT_SSLCERT.md +++ b/docs/libcurl/opts/CURLOPT_SSLCERT.md @@ -11,11 +11,7 @@ See-also: Protocol: - TLS TLS-backend: - - OpenSSL - - GnuTLS - - mbedTLS - - Schannel - - wolfSSL + - All Added-in: 7.1 --- @@ -70,12 +66,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SSLCERTTYPE.md b/docs/libcurl/opts/CURLOPT_SSLCERTTYPE.md index acf875dfb5c6..849701608384 100644 --- a/docs/libcurl/opts/CURLOPT_SSLCERTTYPE.md +++ b/docs/libcurl/opts/CURLOPT_SSLCERTTYPE.md @@ -58,13 +58,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SSLCERT_BLOB.md b/docs/libcurl/opts/CURLOPT_SSLCERT_BLOB.md index 5d121de2dec4..aa69fbbc896a 100644 --- a/docs/libcurl/opts/CURLOPT_SSLCERT_BLOB.md +++ b/docs/libcurl/opts/CURLOPT_SSLCERT_BLOB.md @@ -62,7 +62,7 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; struct curl_blob stblob; stblob.data = certificateData; stblob.len = filesize; @@ -71,7 +71,7 @@ int main(void) 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SSLENGINE.md b/docs/libcurl/opts/CURLOPT_SSLENGINE.md index 0983e93a51df..85aa7753ec58 100644 --- a/docs/libcurl/opts/CURLOPT_SSLENGINE.md +++ b/docs/libcurl/opts/CURLOPT_SSLENGINE.md @@ -56,10 +56,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); curl_easy_setopt(curl, CURLOPT_SSLENGINE, "dynamic"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SSLENGINE_DEFAULT.md b/docs/libcurl/opts/CURLOPT_SSLENGINE_DEFAULT.md index 72e908b76eab..87aab0c2bb3f 100644 --- a/docs/libcurl/opts/CURLOPT_SSLENGINE_DEFAULT.md +++ b/docs/libcurl/opts/CURLOPT_SSLENGINE_DEFAULT.md @@ -46,11 +46,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SSLKEY.md b/docs/libcurl/opts/CURLOPT_SSLKEY.md index 7d311aeec89d..f590e16e9ed2 100644 --- a/docs/libcurl/opts/CURLOPT_SSLKEY.md +++ b/docs/libcurl/opts/CURLOPT_SSLKEY.md @@ -15,6 +15,7 @@ TLS-backend: - mbedTLS - Schannel - wolfSSL + - Rustls Added-in: 7.9.3 --- @@ -59,12 +60,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SSLKEYTYPE.md b/docs/libcurl/opts/CURLOPT_SSLKEYTYPE.md index 0a996fc05468..aef7fd5f8d50 100644 --- a/docs/libcurl/opts/CURLOPT_SSLKEYTYPE.md +++ b/docs/libcurl/opts/CURLOPT_SSLKEYTYPE.md @@ -63,13 +63,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SSLKEY_BLOB.md b/docs/libcurl/opts/CURLOPT_SSLKEY_BLOB.md index 515fa91b3894..a062d39deba8 100644 --- a/docs/libcurl/opts/CURLOPT_SSLKEY_BLOB.md +++ b/docs/libcurl/opts/CURLOPT_SSLKEY_BLOB.md @@ -61,7 +61,7 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; struct curl_blob blob; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); blob.data = certificateData; @@ -75,7 +75,7 @@ int main(void) 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SSL_CIPHER_LIST.md b/docs/libcurl/opts/CURLOPT_SSL_CIPHER_LIST.md index c71a58d6850d..1bbbf6e8c527 100644 --- a/docs/libcurl/opts/CURLOPT_SSL_CIPHER_LIST.md +++ b/docs/libcurl/opts/CURLOPT_SSL_CIPHER_LIST.md @@ -17,7 +17,7 @@ TLS-backend: - Schannel - wolfSSL - mbedTLS - - rustls + - Rustls - GnuTLS Added-in: 7.9 --- @@ -80,12 +80,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); curl_easy_setopt(curl, CURLOPT_SSL_CIPHER_LIST, "ECDHE-ECDSA-CHACHA20-POLY1305:" "ECDHE-RSA-CHACHA20-POLY1305"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SSL_CTX_DATA.md b/docs/libcurl/opts/CURLOPT_SSL_CTX_DATA.md index 6dc81a086710..d8fac3b2e251 100644 --- a/docs/libcurl/opts/CURLOPT_SSL_CTX_DATA.md +++ b/docs/libcurl/opts/CURLOPT_SSL_CTX_DATA.md @@ -81,9 +81,10 @@ static CURLcode sslctx_function(CURL *curl, void *sslctx, void *pointer) int main(void) { - CURL *ch; - CURLcode rv; - char *mypem = /* CA cert in PEM format, replace the XXXs */ + CURL *curl; + CURLcode result; + /* CA cert in PEM format, replace the XXXs */ + char *mypem = "-----BEGIN CERTIFICATE-----\n" "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" @@ -94,23 +95,23 @@ int main(void) "-----END CERTIFICATE-----\n"; curl_global_init(CURL_GLOBAL_ALL); - ch = curl_easy_init(); + curl = 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(curl, CURLOPT_SSLCERTTYPE, "PEM"); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); + curl_easy_setopt(curl, 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) + curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function); + curl_easy_setopt(curl, CURLOPT_SSL_CTX_DATA, mypem); + result = curl_easy_perform(curl); + if(!result) printf("*** transfer succeeded ***\n"); else printf("*** transfer failed ***\n"); - curl_easy_cleanup(ch); + curl_easy_cleanup(curl); curl_global_cleanup(); - return rv; + return (int)result; } ~~~ diff --git a/docs/libcurl/opts/CURLOPT_SSL_CTX_FUNCTION.md b/docs/libcurl/opts/CURLOPT_SSL_CTX_FUNCTION.md index 75e1dc8edb9d..dff37bb14491 100644 --- a/docs/libcurl/opts/CURLOPT_SSL_CTX_FUNCTION.md +++ b/docs/libcurl/opts/CURLOPT_SSL_CTX_FUNCTION.md @@ -134,9 +134,10 @@ static CURLcode sslctx_function(CURL *curl, void *sslctx, void *pointer) int main(void) { - CURL *ch; - CURLcode rv; - char *mypem = /* CA cert in PEM format, replace the XXXs */ + CURL *curl; + CURLcode result; + /* CA cert in PEM format, replace the XXXs */ + char *mypem = "-----BEGIN CERTIFICATE-----\n" "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" @@ -147,23 +148,23 @@ int main(void) "-----END CERTIFICATE-----\n"; curl_global_init(CURL_GLOBAL_ALL); - ch = curl_easy_init(); + curl = 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(curl, CURLOPT_SSLCERTTYPE, "PEM"); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); + curl_easy_setopt(curl, 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) + curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, *sslctx_function); + curl_easy_setopt(curl, CURLOPT_SSL_CTX_DATA, mypem); + result = curl_easy_perform(curl); + if(!result) printf("*** transfer succeeded ***\n"); else printf("*** transfer failed ***\n"); - curl_easy_cleanup(ch); + curl_easy_cleanup(curl); curl_global_cleanup(); - return rv; + return (int)result; } ~~~ diff --git a/docs/libcurl/opts/CURLOPT_SSL_EC_CURVES.md b/docs/libcurl/opts/CURLOPT_SSL_EC_CURVES.md index fcdef1d5b466..674e1ac6d5e9 100644 --- a/docs/libcurl/opts/CURLOPT_SSL_EC_CURVES.md +++ b/docs/libcurl/opts/CURLOPT_SSL_EC_CURVES.md @@ -53,10 +53,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SSL_ENABLE_ALPN.md b/docs/libcurl/opts/CURLOPT_SSL_ENABLE_ALPN.md index a9e20a68d397..2e0399d0fa6b 100644 --- a/docs/libcurl/opts/CURLOPT_SSL_ENABLE_ALPN.md +++ b/docs/libcurl/opts/CURLOPT_SSL_ENABLE_ALPN.md @@ -45,10 +45,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); curl_easy_setopt(curl, CURLOPT_SSL_ENABLE_ALPN, 0L); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SSL_ENABLE_NPN.md b/docs/libcurl/opts/CURLOPT_SSL_ENABLE_NPN.md index e8a6649bfdbb..46b8c9dbb4e3 100644 --- a/docs/libcurl/opts/CURLOPT_SSL_ENABLE_NPN.md +++ b/docs/libcurl/opts/CURLOPT_SSL_ENABLE_NPN.md @@ -47,10 +47,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); curl_easy_setopt(curl, CURLOPT_SSL_ENABLE_NPN, 1L); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.md b/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.md index 2065fe6f1660..7767b0528027 100644 --- a/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.md +++ b/docs/libcurl/opts/CURLOPT_SSL_OPTIONS.md @@ -79,8 +79,8 @@ 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) and with OpenSSL and its forks (LibreSSL, BoringSSL, etc) on Windows (Added in 7.71.0). -This works with rustls on Windows, macOS, Android and iOS. On Linux it is -equivalent to using the Mozilla CA certificate bundle. When used with rustls +This works with Rustls on Windows, macOS, Android and iOS. On Linux it is +equivalent to using the Mozilla CA certificate bundle. When used with Rustls _only_ the native CA store is consulted, not other locations set at run time or build time. (Added in 8.13.0) @@ -100,7 +100,7 @@ Tell libcurl to try sending application data as TLS1.3 early data. This option is supported for GnuTLS, wolfSSL, quictls and OpenSSL (but not BoringSSL or AWS-LC). It works on TCP and QUIC connections using ngtcp2. This option works on a best effort basis, -in cases when it wasn't possible to send early data the request is resent +in cases when it was not possible to send early data the request is resent normally post-handshake. This option does not work when using QUIC. (Added in 8.11.0 for GnuTLS and 8.13.0 for wolfSSL, quictls and OpenSSL) @@ -118,12 +118,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); /* weaken TLS only for use with silly servers */ curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_ALLOW_BEAST | CURLSSLOPT_NO_REVOKE); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SSL_SESSIONID_CACHE.md b/docs/libcurl/opts/CURLOPT_SSL_SESSIONID_CACHE.md index 6f0d527b83f3..2e0c7c6fc0d4 100644 --- a/docs/libcurl/opts/CURLOPT_SSL_SESSIONID_CACHE.md +++ b/docs/libcurl/opts/CURLOPT_SSL_SESSIONID_CACHE.md @@ -50,11 +50,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SSL_SIGNATURE_ALGORITHMS.md b/docs/libcurl/opts/CURLOPT_SSL_SIGNATURE_ALGORITHMS.md index 4fce470bf812..4e7644719c08 100644 --- a/docs/libcurl/opts/CURLOPT_SSL_SIGNATURE_ALGORITHMS.md +++ b/docs/libcurl/opts/CURLOPT_SSL_SIGNATURE_ALGORITHMS.md @@ -60,11 +60,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); curl_easy_setopt(curl, CURLOPT_SSL_SIGNATURE_ALGORITHMS, "DSA+SHA256:rsa_pss_pss_sha256"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SSL_VERIFYSTATUS.md b/docs/libcurl/opts/CURLOPT_SSL_VERIFYSTATUS.md index 14e1ab08b084..b1d373eef69c 100644 --- a/docs/libcurl/opts/CURLOPT_SSL_VERIFYSTATUS.md +++ b/docs/libcurl/opts/CURLOPT_SSL_VERIFYSTATUS.md @@ -51,11 +51,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_SUPPRESS_CONNECT_HEADERS.md b/docs/libcurl/opts/CURLOPT_SUPPRESS_CONNECT_HEADERS.md index b05824630bb7..e86be358edf6 100644 --- a/docs/libcurl/opts/CURLOPT_SUPPRESS_CONNECT_HEADERS.md +++ b/docs/libcurl/opts/CURLOPT_SUPPRESS_CONNECT_HEADERS.md @@ -83,7 +83,7 @@ int main(void) 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_PROXY, "http://proxy.example:3128"); curl_easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, 1L); curl_easy_setopt(curl, CURLOPT_SUPPRESS_CONNECT_HEADERS, 1L); diff --git a/docs/libcurl/opts/CURLOPT_TELNETOPTIONS.md b/docs/libcurl/opts/CURLOPT_TELNETOPTIONS.md index f306c64fa29e..8cab6200bca4 100644 --- a/docs/libcurl/opts/CURLOPT_TELNETOPTIONS.md +++ b/docs/libcurl/opts/CURLOPT_TELNETOPTIONS.md @@ -51,13 +51,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); curl_slist_free_all(options); } diff --git a/docs/libcurl/opts/CURLOPT_TFTP_BLKSIZE.md b/docs/libcurl/opts/CURLOPT_TFTP_BLKSIZE.md index dd299ec922e2..d2de3c19c749 100644 --- a/docs/libcurl/opts/CURLOPT_TFTP_BLKSIZE.md +++ b/docs/libcurl/opts/CURLOPT_TFTP_BLKSIZE.md @@ -45,11 +45,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_TLS13_CIPHERS.md b/docs/libcurl/opts/CURLOPT_TLS13_CIPHERS.md index 62f734f9633b..07dcc79c6443 100644 --- a/docs/libcurl/opts/CURLOPT_TLS13_CIPHERS.md +++ b/docs/libcurl/opts/CURLOPT_TLS13_CIPHERS.md @@ -17,7 +17,7 @@ TLS-backend: - OpenSSL - wolfSSL - mbedTLS - - rustls + - Rustls Added-in: 7.61.0 --- @@ -70,11 +70,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_TLSAUTH_PASSWORD.md b/docs/libcurl/opts/CURLOPT_TLSAUTH_PASSWORD.md index d6c871118ce0..8ff3d95c582d 100644 --- a/docs/libcurl/opts/CURLOPT_TLSAUTH_PASSWORD.md +++ b/docs/libcurl/opts/CURLOPT_TLSAUTH_PASSWORD.md @@ -56,12 +56,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_TLSAUTH_TYPE.md b/docs/libcurl/opts/CURLOPT_TLSAUTH_TYPE.md index 64ce85e5db43..078c41c253d2 100644 --- a/docs/libcurl/opts/CURLOPT_TLSAUTH_TYPE.md +++ b/docs/libcurl/opts/CURLOPT_TLSAUTH_TYPE.md @@ -60,12 +60,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_TLSAUTH_USERNAME.md b/docs/libcurl/opts/CURLOPT_TLSAUTH_USERNAME.md index 230c3babee22..654d858f8339 100644 --- a/docs/libcurl/opts/CURLOPT_TLSAUTH_USERNAME.md +++ b/docs/libcurl/opts/CURLOPT_TLSAUTH_USERNAME.md @@ -55,12 +55,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_TRAILERFUNCTION.md b/docs/libcurl/opts/CURLOPT_TRAILERFUNCTION.md index 06362337658f..716967d88adf 100644 --- a/docs/libcurl/opts/CURLOPT_TRAILERFUNCTION.md +++ b/docs/libcurl/opts/CURLOPT_TRAILERFUNCTION.md @@ -78,7 +78,7 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; /* Set the URL of the request */ curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/"); @@ -91,13 +91,13 @@ int main(void) struct curl_slist *headers = NULL; headers = curl_slist_append(headers, "Trailer: My-super-awesome-trailer"); - res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + result = 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); diff --git a/docs/libcurl/opts/CURLOPT_TRANSFERTEXT.md b/docs/libcurl/opts/CURLOPT_TRANSFERTEXT.md index 4923f33d8ff9..f99dc8df5e42 100644 --- a/docs/libcurl/opts/CURLOPT_TRANSFERTEXT.md +++ b/docs/libcurl/opts/CURLOPT_TRANSFERTEXT.md @@ -48,10 +48,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "ftp://example.com/textfile"); curl_easy_setopt(curl, CURLOPT_TRANSFERTEXT, 1L); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_UPLOAD_BUFFERSIZE.md b/docs/libcurl/opts/CURLOPT_UPLOAD_BUFFERSIZE.md index 209ea32e4e33..746d14c0dd41 100644 --- a/docs/libcurl/opts/CURLOPT_UPLOAD_BUFFERSIZE.md +++ b/docs/libcurl/opts/CURLOPT_UPLOAD_BUFFERSIZE.md @@ -59,13 +59,13 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_USERNAME.md b/docs/libcurl/opts/CURLOPT_USERNAME.md index 736c80cf81d7..916c9dd831d2 100644 --- a/docs/libcurl/opts/CURLOPT_USERNAME.md +++ b/docs/libcurl/opts/CURLOPT_USERNAME.md @@ -70,12 +70,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin"); curl_easy_setopt(curl, CURLOPT_USERNAME, "clark"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_USERPWD.md b/docs/libcurl/opts/CURLOPT_USERPWD.md index ba54949bee68..e3727baec9f2 100644 --- a/docs/libcurl/opts/CURLOPT_USERPWD.md +++ b/docs/libcurl/opts/CURLOPT_USERPWD.md @@ -79,12 +79,12 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/foo.bin"); curl_easy_setopt(curl, CURLOPT_USERPWD, "clark:kent"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } diff --git a/docs/libcurl/opts/CURLOPT_USE_SSL.md b/docs/libcurl/opts/CURLOPT_USE_SSL.md index 9a2d2abe5e9a..0729f6e84ee2 100644 --- a/docs/libcurl/opts/CURLOPT_USE_SSL.md +++ b/docs/libcurl/opts/CURLOPT_USE_SSL.md @@ -45,7 +45,7 @@ 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. +connection if the negotiation fails. ## CURLUSESSL_CONTROL diff --git a/docs/libcurl/opts/CURLOPT_WRITEFUNCTION.md b/docs/libcurl/opts/CURLOPT_WRITEFUNCTION.md index 973a0aea754e..8cc97a6e40cd 100644 --- a/docs/libcurl/opts/CURLOPT_WRITEFUNCTION.md +++ b/docs/libcurl/opts/CURLOPT_WRITEFUNCTION.md @@ -106,8 +106,8 @@ static size_t cb(char *data, size_t size, size_t nmemb, void *clientp) int main(void) { - struct memory chunk = {0}; - CURLcode res; + struct memory chunk = { 0 }; + CURLcode result; CURL *curl = curl_easy_init(); if(curl) { /* send all data to this function */ @@ -117,7 +117,7 @@ int main(void) curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); /* send a request */ - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); /* remember to free the buffer */ free(chunk.response); diff --git a/docs/libcurl/opts/CURLOPT_WS_OPTIONS.md b/docs/libcurl/opts/CURLOPT_WS_OPTIONS.md index d1488a762b14..a76396f38c8f 100644 --- a/docs/libcurl/opts/CURLOPT_WS_OPTIONS.md +++ b/docs/libcurl/opts/CURLOPT_WS_OPTIONS.md @@ -64,11 +64,11 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; 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, CURLWS_RAW_MODE); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/libcurl/opts/CURLOPT_XOAUTH2_BEARER.md b/docs/libcurl/opts/CURLOPT_XOAUTH2_BEARER.md index d80e38ed78cd..894c1384a5e2 100644 --- a/docs/libcurl/opts/CURLOPT_XOAUTH2_BEARER.md +++ b/docs/libcurl/opts/CURLOPT_XOAUTH2_BEARER.md @@ -56,10 +56,10 @@ int main(void) { CURL *curl = curl_easy_init(); if(curl) { - CURLcode res; + CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, "pop3://example.com/"); curl_easy_setopt(curl, CURLOPT_XOAUTH2_BEARER, "1ab9cb22bf269a7"); - res = curl_easy_perform(curl); + result = curl_easy_perform(curl); curl_easy_cleanup(curl); } } diff --git a/docs/mk-ca-bundle.md b/docs/mk-ca-bundle.md index fe68635263a6..bb5b7b1a48f9 100644 --- a/docs/mk-ca-bundle.md +++ b/docs/mk-ca-bundle.md @@ -122,6 +122,5 @@ 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: - -https://p11-glue.freedesktop.org/doc/storing-trust-policy/storing-trust-existing.html +The file format used by Mozilla for this trust information is [documented +here](https://p11-glue.github.io/p11-glue/doc/storing-trust-policy/storing-trust-existing.html). diff --git a/docs/runtests.md b/docs/runtests.md index 4a7ddf5c0bdf..c81172403a17 100644 --- a/docs/runtests.md +++ b/docs/runtests.md @@ -180,6 +180,15 @@ regression test suite. Lists all test case names. +## `-m=[seconds]` + +Set timeout for curl commands in tests. + +## `--min=[count]` + +Set the minimum number of tests to run. This overrides the `CURL_TEST_MIN` +environment variable, if any. + ## `-n` Disable the check for and use of valgrind. diff --git a/docs/testcurl.md b/docs/testcurl.md index e4acab6db7de..b5149e098b57 100644 --- a/docs/testcurl.md +++ b/docs/testcurl.md @@ -102,7 +102,7 @@ snapshots automatically): $ mkdir curl-testing $ cd curl-testing - $ git clone https://github.com/curl/curl.git + $ git clone https://github.com/curl/curl With the curl sources checked out, or downloaded, you can start testing right away. If you want to use *testcurl* without command line arguments and to have diff --git a/docs/tests/FILEFORMAT.md b/docs/tests/FILEFORMAT.md index 91aa9a587028..4749d809e0d2 100644 --- a/docs/tests/FILEFORMAT.md +++ b/docs/tests/FILEFORMAT.md @@ -11,10 +11,9 @@ XML. All data for a single test case resides in a single ASCII file. Labels mark the beginning and the end of all sections, and each label must be written in its own line. Comments are either XML-style (enclosed with ``) or shell script style (beginning with `#`) and must appear on their own -lines and not alongside actual test data. Most test data files are -syntactically valid XML, although a few files are not (lack of support for -character entities and the preservation of CR/LF characters at the end of -lines are the biggest differences). +lines and not alongside actual test data. Test data files are syntactically +valid XML; lack of support for character entities is a big difference but macros +like %CR fill that particular role here. Each test case source exists as a file matching the format `tests/data/testNUM`, where `NUM` is the unique test number, and must begin @@ -76,6 +75,26 @@ For example, to insert the word hello 100 times: %repeat[100 x hello]% +## Whitespace + +To force CRLF newline, add this macro to the end of the line: + + %CR - carriage return + +To add significant whitespace characters at the end of the line, or to empty +lines: + + %SP - space + %TAB - horizontal tab + +## Special characters + +Macros to help keep data files XML-compliant: + + %AMP - Ampersand: `&` + %GT - Greater-than sign: `>` + %LT - Less-than sign: `<` + ## Insert capped epoch days Mostly to test capped cookie expire dates: `%days[NUM]` inserts the number of @@ -94,6 +113,12 @@ the include instruction: %include filename% +Or, a variant of the above where the file is loaded as a newline-agnostic +text file, and whitespace, special character macros and variables expanded +after inclusion: + + %includetext filename% + ## Conditional lines Lines in the test file can be made to appear conditionally on a specific @@ -222,7 +247,7 @@ When running a unit test and the keywords include `unittest`, the `` section can be left empty to use the standard unit test tool name `unitN` where `N` is the test number. -The `text-ci` make target automatically skips test with the `flaky` keyword. +The `test-ci` make target automatically skips test with the `flaky` keyword. Tests that have strict timing dependencies have the `timing-dependent` keyword. These are intended to eventually be treated specially on CI builds which are @@ -233,7 +258,7 @@ similar. ## `` -### `` +### `` data to be sent to the client on its request and later verified that it arrived safely. Set `nocheck="yes"` to prevent the test script from verifying @@ -261,16 +286,19 @@ used as "raw" data. `nonewline=yes` means that the last byte (the trailing newline character) should be cut off from the data before sending or comparing it. -`crlf=yes` forces *header* newlines to become CRLF even if not written so in -the source file. Note that this makes runtests.pl parse and "guess" what is a -header and what is not in order to apply the CRLF line endings appropriately. +`crlf=yes` forces the newlines to become CRLF even if not written so in the +test. + +`crlf=headers` forces *header* newlines to become CRLF even if not written so +in the source file. Note that this makes runtests.pl parse and "guess" what is +a header and what is not in order to apply the CRLF line endings appropriately. For FTP file listings, the `` section is be used *only* if you make sure that there has been a CWD done first to a directory named `test-[NUM]` where `NUM` is the test case number. Otherwise the ftp server cannot know from which test file to load the list content. -### `` +### `` Send back this contents instead of the `` one. The `NUM` is set by: @@ -289,15 +317,22 @@ to complete a transfer. The response to each request is found in its own data section. Validating the entire negotiation sequence can be done by specifying a `datacheck` section. -### `` +### `` The connect section is used instead of the 'data' for all CONNECT requests. The remainder of the rules for the data section then apply but with a connect prefix. +`crlf=yes` forces the newlines to become CRLF even if not written so in the +test. + +`crlf=headers` forces *header* newlines to become CRLF even if not written so +in the source file. Note that this makes runtests.pl parse and "guess" what is +a header and what is not in order to apply the CRLF line endings appropriately. + ### `` Address type and address details as logged by the SOCKS proxy. -### `` +### `` if the data is sent but this is what should be checked afterwards. If `nonewline=yes` is set, runtests cuts off the trailing newline from the data before comparing with the one actually received by the client. @@ -305,7 +340,7 @@ before comparing with the one actually received by the client. Use the `mode="text"` attribute if the output is in text mode on platforms that have a text/binary difference. -### `` +### `` The contents of numbered `datacheck` sections are appended to the non-numbered one. @@ -477,7 +512,7 @@ Features testable here are: - `large-size` (size_t is larger than 32-bit) - `libssh2` - `libssh` -- `oldlibssh` (versions before 0.9.4) +- `badlibssh` (libssh configuration incompatible with the test suite) - `libz` - `local-http`. The HTTP server runs on 127.0.0.1 - `manual` @@ -554,20 +589,11 @@ command has been run. If the variable name has no assignment, no `=`, then that variable is just deleted. -### `` +### `` Command line to run. -Note that the URL that gets passed to the server actually controls what data -that is returned. The last slash in the URL must be followed by a number. That -number (N) is used by the test-server to load test case N and return the data -that is defined within the `` section. - -If there is no test number found above, the HTTP test server uses the number -following the last dot in the given hostname (made so that a CONNECT can still -pass on test number) so that "foo.bar.123" gets treated as test case -123. Alternatively, if an IPv6 address is provided to CONNECT, the last -hexadecimal group in the address is used as the test number. For example the -address "[1234::ff]" would be treated as test case 255. +If the command spans multiple lines, they are concatenated with a space added +between them. Set `type="perl"` to write the test case as a perl script. It implies that there is no memory debugging and valgrind gets shut off for this test. @@ -585,6 +611,9 @@ otherwise written to verify stdout. Set `option="no-include"` to prevent the test script to slap on the `--include` argument. +Set `option="no-memdebug"` to make the test run without the memdebug tracking +system. For tests that are incompatible - multi-threaded for example. + Set `option="no-q"` avoid using `-q` as the first argument in the curl command line. @@ -605,13 +634,16 @@ parameter is the not negative integer number of seconds for the delay. This 'delay' attribute is intended for specific test cases, and normally not needed. -### `` +### `` This creates the named file with this content before the test case is run, which is useful if the test case needs a file to act on. If `nonewline="yes"` is used, the created file gets the final newline stripped off. +`crlf=yes` forces the newlines to become CRLF even if not written so in the +test. + ### `` 1 to 4 can be appended to 'file' to create more files. @@ -621,12 +653,15 @@ off. ### `` -### `` +### `` Pass this given data on stdin to the tool. If `nonewline` is set, we cut off the trailing newline of this given data before comparing with the one actually received by the client +`crlf=yes` forces the newlines to become CRLF even if not written so in the +test. + ## `` If `test-duphandle` is a listed item here, this is not run when @@ -655,7 +690,7 @@ command exists with a non-zero status code, the test is considered failed. A list of directory entries that are checked for after the test has completed and that must not exist. A listed entry existing causes the test to fail. -### `` +### `` the protocol dump curl should transmit, if `nonewline` is set, we cut off the trailing newline of this given data before comparing with the one actually @@ -665,14 +700,18 @@ comparisons are made. `crlf=yes` forces the newlines to become CRLF even if not written so in the test. -### `` +`crlf=headers` forces *header* newlines to become CRLF even if not written so +in the source file. Note that this makes runtests.pl parse and "guess" what is +a header and what is not in order to apply the CRLF line endings appropriately. + +### `` The protocol dump curl should transmit to an HTTP proxy (when the http-proxy server is used), if `nonewline` is set, we cut off the trailing newline of this given data before comparing with the one actually sent by the client The `` and `` rules are applied before comparisons are made. -### `` +### `` This verifies that this data was passed to stderr. Use the mode="text" attribute if the output is in text mode on platforms that @@ -681,10 +720,14 @@ have a text/binary difference. `crlf=yes` forces the newlines to become CRLF even if not written so in the test. +`crlf=headers` forces *header* newlines to become CRLF even if not written so +in the source file. Note that this makes runtests.pl parse and "guess" what is +a header and what is not in order to apply the CRLF line endings appropriately. + If `nonewline` is set, we cut off the trailing newline of this given data before comparing with the one actually received by the client -### `` +### `` This verifies that this data was passed to stdout. Use the mode="text" attribute if the output is in text mode on platforms that @@ -696,6 +739,10 @@ before comparing with the one actually received by the client `crlf=yes` forces the newlines to become CRLF even if not written so in the test. +`crlf=headers` forces *header* newlines to become CRLF even if not written so +in the source file. Note that this makes runtests.pl parse and "guess" what is +a header and what is not in order to apply the CRLF line endings appropriately. + `loadfile="filename"` makes loading the data from an external file. ### `` @@ -706,11 +753,18 @@ that the set limits are not exceeded. Supported limits: Allocations: [number of allocation calls] Maximum allocated: [maximum concurrent memory allocated] -### `` +### `` The file's contents must be identical to this after the test is complete. Use the mode="text" attribute if the output is in text mode on platforms that have a text/binary difference. +`crlf=yes` forces the newlines to become CRLF even if not written so in the +test. + +`crlf=headers` forces *header* newlines to become CRLF even if not written so +in the source file. Note that this makes runtests.pl parse and "guess" what is +a header and what is not in order to apply the CRLF line endings appropriately. + ### `` 1 to 4 can be appended to 'file' to compare more files. diff --git a/docs/tests/HTTP.md b/docs/tests/HTTP.md index afbfe9e5bd96..658abac25505 100644 --- a/docs/tests/HTTP.md +++ b/docs/tests/HTTP.md @@ -6,7 +6,9 @@ SPDX-License-Identifier: curl # The curl HTTP Test Suite -This is an additional test suite using a combination of Apache httpd and nghttpx servers to perform various tests beyond the capabilities of the standard curl test suite. +This is an additional test suite using a combination of Apache httpd and +nghttpx servers to perform various tests beyond the capabilities of the +standard curl test suite. # Usage @@ -23,13 +25,17 @@ collected 5 items tests/http/test_01_basic.py ..... ``` -Pytest takes arguments. `-v` increases its verbosity and can be used several times. `-k ` can be used to run only matching test cases. The `expr` can be something resembling a python test or just a string that needs to match test cases in their names. +Pytest takes arguments. `-v` increases its verbosity and can be used several +times. `-k ` can be used to run only matching test cases. The `expr` can +be something resembling a python test or just a string that needs to match +test cases in their names. ``` curl/tests/http> pytest -vv -k test_01_02 ``` -runs all test cases that have `test_01_02` in their name. This does not have to be the start of the name. +runs all test cases that have `test_01_02` in their name. This does not have +to be the start of the name. Depending on your setup, some test cases may be skipped and appear as `s` in the output. If you run pytest verbose, it also gives you the reason for @@ -40,7 +46,8 @@ skipping. You need: 1. a recent Python, the `cryptography` module and, of course, `pytest` -2. an apache httpd development version. On Debian/Ubuntu, the package `apache2-dev` has this +2. an apache httpd development version. On Debian/Ubuntu, the package + `apache2-dev` has this 3. a local `curl` project build 3. optionally, a `nghttpx` with HTTP/3 enabled or h3 test cases are skipped @@ -48,33 +55,49 @@ You need: Via curl's `configure` script you may specify: - * `--with-test-nghttpx=` if you have nghttpx to use somewhere outside your `$PATH`. - * `--with-test-httpd=` if you have an Apache httpd installed somewhere else. On Debian/Ubuntu it will otherwise look into `/usr/bin` and `/usr/sbin` to find those. - * `--with-test-caddy=` if you have a Caddy web server installed somewhere else. - * `--with-test-vsftpd=` if you have a vsftpd ftp server installed somewhere else. + * `--with-test-nghttpx=` if you have nghttpx to use + somewhere outside your `$PATH`. + + * `--with-test-httpd=` if you have an Apache httpd + installed somewhere else. On Debian/Ubuntu it otherwise looks into + `/usr/bin` and `/usr/sbin` to find those. + + * `--with-test-caddy=` if you have a Caddy web server + installed somewhere else. + + * `--with-test-vsftpd=` if you have a vsftpd ftp + server installed somewhere else. + * `--with-test-danted=` if you have `dante-server` installed ## Usage Tips -Several test cases are parameterized, for example with the HTTP version to use. If you want to run a test with a particular protocol only, use a command line like: +Several test cases are parameterized, for example with the HTTP version to +use. If you want to run a test with a particular protocol only, use a command +line like: ``` curl/tests/http> pytest -k "test_02_06 and h2" ``` -Test cases can be repeated, with the `pytest-repeat` module (`pip install pytest-repeat`). Like in: +Test cases can be repeated, with the `pytest-repeat` module (`pip install +pytest-repeat`). Like in: ``` curl/tests/http> pytest -k "test_02_06 and h2" --count=100 ``` -which then runs this test case a hundred times. In case of flaky tests, you can make pytest stop on the first one with: +which then runs this test case a hundred times. In case of flaky tests, you +can make pytest stop on the first one with: ``` curl/tests/http> pytest -k "test_02_06 and h2" --count=100 --maxfail=1 ``` -which allow you to inspect output and log files for the failed run. Speaking of log files, the verbosity of pytest is also used to collect curl trace output. If you specify `-v` three times, the `curl` command is started with `--trace`: +which allow you to inspect output and log files for the failed run. Speaking +of log files, the verbosity of pytest is also used to collect curl trace +output. If you specify `-v` three times, the `curl` command is started with +`--trace`: ``` curl/tests/http> pytest -vvv -k "test_02_06 and h2" --count=100 --maxfail=1 @@ -84,7 +107,10 @@ all of curl's output and trace file are found in `tests/http/gen/curl`. ## Writing Tests -There is a lot of [`pytest` documentation](https://docs.pytest.org/) with examples. No use in repeating that here. Assuming you are somewhat familiar with it, it is useful how *this* general test suite is setup. Especially if you want to add test cases. +There is a lot of [`pytest` documentation](https://docs.pytest.org/) with +examples. No use in repeating that here. Assuming you are somewhat familiar +with it, it is useful how *this* general test suite is setup. Especially if +you want to add test cases. ### Servers @@ -110,22 +136,44 @@ left behind. ### Test Cases -Tests making use of these fixtures have them in their parameter list. This tells pytest that a particular test needs them, so it has to create them. Since one can invoke pytest for just a single test, it is important that a test references the ones it needs. +Tests making use of these fixtures have them in their parameter list. This +tells pytest that a particular test needs them, so it has to create them. +Since one can invoke pytest for just a single test, it is important that a +test references the ones it needs. -All test cases start with `test_` in their name. We use a double number scheme to group them. This makes it ease to run only specific tests and also give a short mnemonic to communicate trouble with others in the project. Otherwise you are free to name test cases as you think fitting. +All test cases start with `test_` in their name. We use a double number scheme +to group them. This makes it ease to run only specific tests and also give a +short mnemonic to communicate trouble with others in the project. Otherwise +you are free to name test cases as you think fitting. -Tests are grouped thematically in a file with a single Python test class. This is convenient if you need a special "fixture" for several tests. "fixtures" can have "class" scope. +Tests are grouped thematically in a file with a single Python test class. This +is convenient if you need a special "fixture" for several tests. "fixtures" +can have "class" scope. -There is a curl helper class that knows how to invoke curl and interpret its output. Among other things, it does add the local CA to the command line, so that SSL connections to the test servers are verified. Nothing prevents anyone from running curl directly, for specific uses not covered by the `CurlClient` class. +There is a curl helper class that knows how to invoke curl and interpret its +output. Among other things, it does add the local CA to the command line, so +that SSL connections to the test servers are verified. Nothing prevents anyone +from running curl directly, for specific uses not covered by the `CurlClient` +class. ### mod_curltest -The module source code is found in `testenv/mod_curltest`. It is compiled using the `apxs` command, commonly provided via the `apache2-dev` package. Compilation is quick and done once at the start of a test run. +The module source code is found in `testenv/mod_curltest`. It is compiled +using the `apxs` command, commonly provided via the `apache2-dev` package. +Compilation is quick and done once at the start of a test run. + +The module adds 2 "handlers" to the Apache server (right now). Handler are +pieces of code that receive HTTP requests and generate the response. Those +handlers are: + +* `curltest-echo`: hooked up on the path `/curltest/echo`. This one echoes + a request and copies all data from the request body to the response body. + Useful for simulating upload and checking that the data arrived as intended. -The module adds 2 "handlers" to the Apache server (right now). Handler are pieces of code that receive HTTP requests and generate the response. Those handlers are: +* `curltest-tweak`: hooked up on the path `/curltest/tweak`. This handler is + more of a Swiss army knife. It interprets parameters from the URL query + string to drive its behavior. -* `curltest-echo`: hooked up on the path `/curltest/echo`. This one echoes a request and copies all data from the request body to the response body. Useful for simulating upload and checking that the data arrived as intended. -* `curltest-tweak`: hooked up on the path `/curltest/tweak`. This handler is more of a Swiss army knife. It interprets parameters from the URL query string to drive its behavior. * `status=nnn`: generate a response with HTTP status code `nnn`. * `chunks=n`: generate `n` chunks of data in the response body, defaults to 3. * `chunk_size=nnn`: each chunk should contain `nnn` bytes of data. Maximum is 16KB right now. diff --git a/docs/tests/TEST-SUITE.md b/docs/tests/TEST-SUITE.md index 2110cfb362ff..6a2e60c81759 100644 --- a/docs/tests/TEST-SUITE.md +++ b/docs/tests/TEST-SUITE.md @@ -23,22 +23,24 @@ SPDX-License-Identifier: curl 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'. + 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. + 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 would 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: + If you would 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: + To see what flags are available for runtests.pl, and what output it emits, + run: - man ./tests/runtests.1 + man ./docs/runtests.1 After a test fails, examine the tests/log directory for stdout, stderr, and output from the servers used in the test. @@ -212,13 +214,13 @@ SPDX-License-Identifier: curl to drown in output. The newly introduced *connection filters* allows one to dynamically increase log verbosity for a particular *filter type*. Example: - CURL_DEBUG=ssl curl -v https://curl.se + CURL_DEBUG=ssl curl -v https://curl.se/ makes the `ssl` connection filter log more details. One may do that for every filter type and also use a combination of names, separated by `,` or space. - CURL_DEBUG=ssl,http/2 curl -v https://curl.se + CURL_DEBUG=ssl,http/2 curl -v https://curl.se/ The order of filter type names is not relevant. Names used here are case insensitive. Note that these names are implementation internals and diff --git a/docs/wcurl.md b/docs/wcurl.md index ab5f956fc029..ab5c3aaa9722 100644 --- a/docs/wcurl.md +++ b/docs/wcurl.md @@ -40,7 +40,7 @@ should be using curl directly if your use case is not covered. By default, **wcurl** does: -## * Percent-encode whitespaces in URLs; +## * Percent-encode whitespace in URLs; ## * Download multiple URLs in parallel if the installed curl's version is \>= 7.66.0 (--parallel); @@ -87,8 +87,8 @@ last value is considered. ## --no-decode-filename -Don't percent-decode the output filename, even if the percent-encoding in the -URL was done by **wcurl**, e.g.: The URL contained whitespaces. +Do not percent-decode the output filename, even if the percent-encoding in the +URL was done by **wcurl**, e.g.: The URL contained whitespace. ## --dry-run @@ -110,7 +110,7 @@ is instead forwarded to the curl invocation. # URL URL to be downloaded. Anything that is not a parameter is considered -an URL. Whitespaces are percent-encoded and the URL is passed to curl, which +an URL. Whitespace is percent-encoded and the URL is passed to curl, which then performs the parsing. May be specified more than once. # EXAMPLES @@ -144,7 +144,7 @@ Download multiple files without a limit of concurrent connections per host (the # REPORTING BUGS If you experience any problems with **wcurl** that you do not experience with -curl, submit an issue on Github: https://github.com/curl/wcurl +curl, submit an issue on GitHub: https://github.com/curl/wcurl # COPYRIGHT diff --git a/include/curl/curl.h b/include/curl/curl.h index 49552558ddb7..250f3f679aab 100644 --- a/include/curl/curl.h +++ b/include/curl/curl.h @@ -229,7 +229,6 @@ struct curl_httppost { set. Added in 7.46.0 */ }; - /* This is a return code for the progress callback that, when returned, will signal libcurl to continue executing the default progress function */ #define CURL_PROGRESSFUNC_CONTINUE 0x10000001 @@ -401,12 +400,12 @@ typedef int (*curl_seek_callback)(void *instream, #define CURL_TRAILERFUNC_ABORT 1 typedef size_t (*curl_read_callback)(char *buffer, - size_t size, - size_t nitems, - void *instream); + size_t size, + size_t nitems, + void *instream); typedef int (*curl_trailer_callback)(struct curl_slist **list, - void *userdata); + void *userdata); typedef enum { CURLSOCKTYPE_IPCXN, /* socket created for a specific IP connection */ @@ -844,7 +843,7 @@ typedef enum { #define CURLAUTH_AWS_SIGV4 (((unsigned long)1)<<7) #define CURLAUTH_ONLY (((unsigned long)1)<<31) #define CURLAUTH_ANY (~CURLAUTH_DIGEST_IE) -#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC|CURLAUTH_DIGEST_IE)) +#define CURLAUTH_ANYSAFE (~(CURLAUTH_BASIC | CURLAUTH_DIGEST_IE)) #define CURLSSH_AUTH_ANY ~0L /* all types supported by the server */ #define CURLSSH_AUTH_NONE 0L /* none allowed, silly but complete */ @@ -916,7 +915,6 @@ typedef int /* return CURLE_OK to accept */ /* or something else to refuse */ - /* parameter for the CURLOPT_USE_SSL option */ #define CURLUSESSL_NONE 0L /* do not attempt to use SSL */ #define CURLUSESSL_TRY 1L /* try using SSL, proceed anyway otherwise */ @@ -1115,7 +1113,6 @@ typedef CURLSTScode (*curl_hstswrite_callback)(CURL *easy, /* *STRINGPOINT is an alias for OBJECTPOINT to allow tools to extract the string options from the header file */ - #define CURLOPT(na,t,nu) na = t + nu #define CURLOPTDEPRECATED(na,t,nu,v,m) na CURL_DEPRECATED(v,m) = t + nu @@ -1874,9 +1871,7 @@ typedef enum { libcurl will ask for the compressed methods it knows of, and if that is not any, it will not ask for transfer-encoding at all even if this - option is set to 1. - - */ + option is set to 1. */ CURLOPT(CURLOPT_TRANSFER_ENCODING, CURLOPTTYPE_LONG, 207), /* Callback function for closing socket (instead of close(2)). The callback @@ -1953,8 +1948,7 @@ typedef enum { /* Pass in a bitmask of "header options" */ CURLOPT(CURLOPT_HEADEROPT, CURLOPTTYPE_VALUES, 229), - /* The public key in DER form used to validate the peer public key - this option is used only if SSL_VERIFYPEER is true */ + /* The public key used to validate the peer public key */ CURLOPT(CURLOPT_PINNEDPUBLICKEY, CURLOPTTYPE_STRINGPOINT, 230), /* Path to Unix domain socket */ @@ -2295,10 +2289,9 @@ typedef enum { #undef CURLOPT_DNS_USE_GLOBAL_CACHE /* soon obsolete */ #endif - - /* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host - name resolves addresses using more than one IP protocol version, this - option might be handy to force libcurl to use a specific IP version. */ +/* Below here follows defines for the CURLOPT_IPRESOLVE option. If a host + name resolves addresses using more than one IP protocol version, this + option might be handy to force libcurl to use a specific IP version. */ #define CURL_IPRESOLVE_WHATEVER 0L /* default, uses addresses to all IP versions that your system allows */ #define CURL_IPRESOLVE_V4 1L /* uses only IPv4 addresses/connections */ @@ -2382,7 +2375,7 @@ enum CURL_NETRC_OPTION { #define CURL_SSLVERSION_MAX_TLSv1_2 (CURL_SSLVERSION_TLSv1_2 << 16) #define CURL_SSLVERSION_MAX_TLSv1_3 (CURL_SSLVERSION_TLSv1_3 << 16) - /* never use, keep last */ +/* never use, keep last */ #define CURL_SSLVERSION_MAX_LAST (CURL_SSLVERSION_LAST << 16) #define CURL_TLSAUTH_NONE 0L @@ -2404,7 +2397,7 @@ enum CURL_TLSAUTH { #define CURL_REDIR_POST_302 2L #define CURL_REDIR_POST_303 4L #define CURL_REDIR_POST_ALL \ - (CURL_REDIR_POST_301|CURL_REDIR_POST_302|CURL_REDIR_POST_303) + (CURL_REDIR_POST_301 | CURL_REDIR_POST_302 | CURL_REDIR_POST_303) #define CURL_TIMECOND_NONE 0L #define CURL_TIMECOND_IFMODSINCE 1L @@ -2419,7 +2412,7 @@ typedef enum { } curl_TimeCond; /* Special size_t value signaling a null-terminated string. */ -#define CURL_ZERO_TERMINATED ((size_t) -1) +#define CURL_ZERO_TERMINATED ((size_t)-1) /* curl_strequal() and curl_strnequal() are subject for removal in a future release */ @@ -2706,7 +2699,6 @@ CURL_EXTERN char *curl_easy_escape(CURL *handle, CURL_EXTERN char *curl_escape(const char *string, int length); - /* * NAME curl_easy_unescape() * @@ -2744,10 +2736,9 @@ CURL_EXTERN void curl_free(void *p); * * curl_global_init() should be invoked exactly once for each application that * uses libcurl and before any call of other libcurl functions. - + * * This function is thread-safe if CURL_VERSION_THREADSAFE is set in the * curl_version_info_data.features flag (fetch by curl_version_info()). - */ CURL_EXTERN CURLcode curl_global_init(long flags); @@ -2788,10 +2779,9 @@ CURL_EXTERN void curl_global_cleanup(void); * * curl_global_trace() can be invoked at application start to * configure which components in curl should participate in tracing. - + * * This function is thread-safe if CURL_VERSION_THREADSAFE is set in the * curl_version_info_data.features flag (fetch by curl_version_info()). - */ CURL_EXTERN CURLcode curl_global_trace(const char *config); @@ -3018,12 +3008,11 @@ typedef enum { #define CURL_GLOBAL_SSL (1<<0) /* no purpose since 7.57.0 */ #define CURL_GLOBAL_WIN32 (1<<1) -#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL|CURL_GLOBAL_WIN32) +#define CURL_GLOBAL_ALL (CURL_GLOBAL_SSL | CURL_GLOBAL_WIN32) #define CURL_GLOBAL_NOTHING 0 #define CURL_GLOBAL_DEFAULT CURL_GLOBAL_ALL #define CURL_GLOBAL_ACK_EINTR (1<<2) - /***************************************************************************** * Setup defines, protos etc for the sharing stuff. */ @@ -3061,7 +3050,6 @@ typedef void (*curl_unlock_function)(CURL *handle, curl_lock_data data, void *userptr); - typedef enum { CURLSHE_OK, /* all is fine */ CURLSHE_BAD_OPTION, /* 1 */ @@ -3265,8 +3253,8 @@ CURL_EXTERN CURLcode curl_easy_pause(CURL *handle, int bitmask); #define CURLPAUSE_SEND (1<<2) #define CURLPAUSE_SEND_CONT (0) -#define CURLPAUSE_ALL (CURLPAUSE_RECV|CURLPAUSE_SEND) -#define CURLPAUSE_CONT (CURLPAUSE_RECV_CONT|CURLPAUSE_SEND_CONT) +#define CURLPAUSE_ALL (CURLPAUSE_RECV | CURLPAUSE_SEND) +#define CURLPAUSE_CONT (CURLPAUSE_RECV_CONT | CURLPAUSE_SEND_CONT) /* * NAME curl_easy_ssls_import() @@ -3311,7 +3299,6 @@ CURL_EXTERN CURLcode curl_easy_ssls_export(CURL *handle, curl_ssls_export_cb *export_fn, void *userptr); - #ifdef __cplusplus } /* end of extern "C" */ #endif diff --git a/include/curl/curlver.h b/include/curl/curlver.h index 19b2bf87521b..5a19dc2f5d7e 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.17.0-DEV" +#define LIBCURL_VERSION "8.18.0-DEV" /* The numeric version number is also available "in parts" by using these defines: */ #define LIBCURL_VERSION_MAJOR 8 -#define LIBCURL_VERSION_MINOR 17 +#define LIBCURL_VERSION_MINOR 18 #define LIBCURL_VERSION_PATCH 0 /* This is the numeric version of the libcurl version number, meant for easier parsing and comparisons by programs. The LIBCURL_VERSION_NUM define will @@ -58,7 +58,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 0x081100 +#define LIBCURL_VERSION_NUM 0x081200 /* * This is the date and time when the full source package was created. The diff --git a/include/curl/easy.h b/include/curl/easy.h index fa1356493798..5b3cdbd64e80 100644 --- a/include/curl/easy.h +++ b/include/curl/easy.h @@ -50,7 +50,7 @@ CURL_EXTERN void curl_easy_cleanup(CURL *curl); * * Request internal information from the curl session with this function. * The third argument MUST be pointing to the specific type of the used option - * which is documented in each manpage of the option. The data pointed to + * which is documented in each man page of the option. The data pointed to * will be filled in accordingly and can be relied upon only if the function * returns CURLE_OK. This function is intended to get used *AFTER* a performed * transfer, all results from this function are undefined until the transfer @@ -58,7 +58,6 @@ CURL_EXTERN void curl_easy_cleanup(CURL *curl); */ CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...); - /* * NAME curl_easy_duphandle() * @@ -67,7 +66,7 @@ CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...); * Creates a new curl session handle with the same options set for the handle * passed in. Duplicating a handle could only be a matter of cloning data and * options, internal state info and things like persistent connections cannot - * be transferred. It is useful in multithreaded applications when you can run + * be transferred. It is useful in multi-threaded applications when you can run * curl_easy_duphandle() for each new thread to avoid a series of identical * curl_easy_setopt() invokes in every thread. */ @@ -108,7 +107,6 @@ CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer, size_t buflen, size_t *n); - /* * NAME curl_easy_upkeep() * diff --git a/include/curl/multi.h b/include/curl/multi.h index 4e30637ef565..f3f66030ca25 100644 --- a/include/curl/multi.h +++ b/include/curl/multi.h @@ -136,25 +136,25 @@ CURL_EXTERN CURLM *curl_multi_init(void); CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle, CURL *curl_handle); - /* - * Name: curl_multi_remove_handle() - * - * Desc: removes a curl handle from the multi stack again - * - * Returns: CURLMcode type, general multi error code. - */ +/* + * Name: curl_multi_remove_handle() + * + * Desc: removes a curl handle from the multi stack again + * + * Returns: CURLMcode type, general multi error code. + */ CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle, CURL *curl_handle); - /* - * Name: curl_multi_fdset() - * - * Desc: Ask curl for its fd_set sets. The app can use these to select() or - * poll() on. We want curl_multi_perform() called as soon as one of - * them are ready. - * - * Returns: CURLMcode type, general multi error code. - */ +/* + * Name: curl_multi_fdset() + * + * Desc: Ask curl for its fd_set sets. The app can use these to select() or + * poll() on. We want curl_multi_perform() called as soon as one of + * them are ready. + * + * Returns: CURLMcode type, general multi error code. + */ CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle, fd_set *read_fd_set, fd_set *write_fd_set, @@ -198,35 +198,35 @@ CURL_EXTERN CURLMcode curl_multi_poll(CURLM *multi_handle, */ CURL_EXTERN CURLMcode curl_multi_wakeup(CURLM *multi_handle); - /* - * Name: curl_multi_perform() - * - * Desc: When the app thinks there is data available for curl it calls this - * function to read/write whatever there is right now. This returns - * as soon as the reads and writes are done. This function does not - * require that there actually is data available for reading or that - * data can be written, it can be called just in case. It returns - * the number of handles that still transfer data in the second - * argument's integer-pointer. - * - * Returns: CURLMcode type, general multi error code. *NOTE* that this only - * returns errors etc regarding the whole multi stack. There might - * still have occurred problems on individual transfers even when - * this returns OK. - */ +/* + * Name: curl_multi_perform() + * + * Desc: When the app thinks there is data available for curl it calls this + * function to read/write whatever there is right now. This returns + * as soon as the reads and writes are done. This function does not + * require that there actually is data available for reading or that + * data can be written, it can be called just in case. It returns + * the number of handles that still transfer data in the second + * argument's integer-pointer. + * + * Returns: CURLMcode type, general multi error code. *NOTE* that this only + * returns errors etc regarding the whole multi stack. There might + * still have occurred problems on individual transfers even when + * this returns OK. + */ CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles); - /* - * Name: curl_multi_cleanup() - * - * Desc: Cleans up and removes a whole multi stack. It does not free or - * touch any individual easy handles in any way. We need to define - * in what state those handles will be if this function is called - * in the middle of a transfer. - * - * Returns: CURLMcode type, general multi error code. - */ +/* + * Name: curl_multi_cleanup() + * + * Desc: Cleans up and removes a whole multi stack. It does not free or + * touch any individual easy handles in any way. We need to define + * in what state those handles will be if this function is called + * in the middle of a transfer. + * + * Returns: CURLMcode type, general multi error code. + */ CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle); /* @@ -278,7 +278,7 @@ CURL_EXTERN const char *curl_multi_strerror(CURLMcode); * Desc: An alternative version of curl_multi_perform() that allows the * application to pass in one of the file descriptors that have been * detected to have "action" on them and let libcurl perform. - * See manpage for details. + * See man page for details. */ #define CURL_POLL_NONE 0 #define CURL_POLL_IN 1 @@ -327,8 +327,8 @@ curl_multi_socket_all(CURLM *multi_handle, int *running_handles); #ifndef CURL_ALLOW_OLD_MULTI_SOCKET /* This macro below was added in 7.16.3 to push users who recompile to use - the new curl_multi_socket_action() instead of the old curl_multi_socket() -*/ + * the new curl_multi_socket_action() instead of the old curl_multi_socket() + */ #define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z) #endif @@ -351,10 +351,10 @@ typedef enum { /* This is the argument passed to the socket callback */ CURLOPT(CURLMOPT_SOCKETDATA, CURLOPTTYPE_OBJECTPOINT, 2), - /* set to 1 to enable pipelining for this multi handle */ + /* set to 1 to enable pipelining for this multi handle */ CURLOPT(CURLMOPT_PIPELINING, CURLOPTTYPE_LONG, 3), - /* This is the timer callback function pointer */ + /* This is the timer callback function pointer */ CURLOPT(CURLMOPT_TIMERFUNCTION, CURLOPTTYPE_FUNCTIONPOINT, 4), /* This is the argument passed to the timer callback */ @@ -429,7 +429,6 @@ typedef enum { CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle, CURLMoption option, ...); - /* * Name: curl_multi_assign() * @@ -454,7 +453,6 @@ CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle, */ CURL_EXTERN CURL **curl_multi_get_handles(CURLM *multi_handle); - typedef enum { CURLMINFO_NONE, /* first, never use this */ /* The number of easy handles currently managed by the multi handle, diff --git a/include/curl/system.h b/include/curl/system.h index 62ed2b0f43aa..a5b3e9eba79a 100644 --- a/include/curl/system.h +++ b/include/curl/system.h @@ -135,21 +135,12 @@ # endif #elif defined(UNDER_CE) -# ifdef __MINGW32CE__ -# 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 -# define CURL_TYPEOF_CURL_SOCKLEN_T int -# else -# define CURL_TYPEOF_CURL_OFF_T __int64 -# define CURL_FORMAT_CURL_OFF_T "I64d" -# define CURL_FORMAT_CURL_OFF_TU "I64u" -# define CURL_SUFFIX_CURL_OFF_T i64 -# define CURL_SUFFIX_CURL_OFF_TU ui64 -# define CURL_TYPEOF_CURL_SOCKLEN_T int -# endif +# define CURL_TYPEOF_CURL_OFF_T __int64 +# define CURL_FORMAT_CURL_OFF_T "I64d" +# define CURL_FORMAT_CURL_OFF_TU "I64u" +# define CURL_SUFFIX_CURL_OFF_T i64 +# define CURL_SUFFIX_CURL_OFF_TU ui64 +# define CURL_TYPEOF_CURL_SOCKLEN_T int #elif defined(__MINGW32__) # include diff --git a/include/curl/typecheck-gcc.h b/include/curl/typecheck-gcc.h index 063cea57e6f2..0642afd91ed2 100644 --- a/include/curl/typecheck-gcc.h +++ b/include/curl/typecheck-gcc.h @@ -24,7 +24,7 @@ * ***************************************************************************/ -/* wraps curl_easy_setopt() with typechecking */ +/* wraps curl_easy_setopt() with type checking */ /* To add a new kind of warning, add an * if(curlcheck_sometype_option(_curl_opt)) @@ -159,7 +159,7 @@ curl_easy_setopt(handle, option, value); \ }) -/* wraps curl_easy_getinfo() with typechecking */ +/* wraps curl_easy_getinfo() with type checking */ #define curl_easy_getinfo(handle, info, arg) \ __extension__({ \ if(__builtin_constant_p(info)) { \ @@ -264,7 +264,6 @@ */ #define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param) - /* the actual warnings, triggered by calling the Wcurl_easy_setopt_err* * functions */ @@ -590,8 +589,9 @@ CURLWARNING(Wcurl_easy_getinfo_err_curl_off_t, #define curlcheck_off_t_info(info) \ (CURLINFO_OFF_T < (info)) - -/* typecheck helpers -- check whether given expression has requested type */ +/* + * typecheck helpers -- check whether given expression has requested type + */ /* For pointers, you can use the curlcheck_ptr/curlcheck_arr macros, * otherwise define a new macro. Search for __builtin_types_compatible_p @@ -641,7 +641,6 @@ CURLWARNING(Wcurl_easy_getinfo_err_curl_off_t, (curlcheck_NULL(expr) || \ __builtin_types_compatible_p(__typeof__(expr), CURL *)) - /* evaluates to true if expr is a long (no matter the signedness) * XXX: for now, int is also accepted (and therefore short and char, which * are promoted to int when passed to a variadic function) */ diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index d9857a50c27f..0f842f0cc12d 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -26,7 +26,7 @@ set(LIBCURL_OUTPUT_NAME "${LIB_NAME}" CACHE STRING "Basename of the curl library set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS ${CURL_DEBUG_MACROS} "BUILDING_LIBCURL") -configure_file("curl_config.h.cmake" "${CMAKE_CURRENT_BINARY_DIR}/curl_config.h") +configure_file("curl_config-cmake.h.in" "${CMAKE_CURRENT_BINARY_DIR}/curl_config.h") # Get CSOURCES, HHEADERS, LIB_RCFILES variables curl_transform_makefile_inc("Makefile.inc" "${CMAKE_CURRENT_BINARY_DIR}/Makefile.inc.cmake") @@ -44,7 +44,7 @@ if(CURL_BUILD_TESTING) # special libcurlu library just for unittests add_library(curlu STATIC EXCLUDE_FROM_ALL ${HHEADERS} ${CSOURCES}) target_compile_definitions(curlu PUBLIC "CURL_STATICLIB" "UNITTESTS") - target_link_libraries(curlu PRIVATE ${CURL_LIBS}) + target_link_libraries(curlu PUBLIC ${CURL_LIBS}) # There is plenty of parallelism when building the testdeps target. # Override the curlu batch size with the maximum to optimize performance. set_target_properties(curlu PROPERTIES UNITY_BUILD_BATCH_SIZE 0 C_CLANG_TIDY "") @@ -151,8 +151,7 @@ if(BUILD_STATIC_LIBS) set_target_properties(${LIB_STATIC} PROPERTIES PREFIX "" OUTPUT_NAME "${LIBCURL_OUTPUT_NAME}" SUFFIX "${STATIC_LIB_SUFFIX}${CMAKE_STATIC_LIBRARY_SUFFIX}" - INTERFACE_COMPILE_DEFINITIONS "CURL_STATICLIB" - INTERFACE_LINK_DIRECTORIES "${CURL_LIBDIRS}") + INTERFACE_COMPILE_DEFINITIONS "CURL_STATICLIB") if(CURL_HIDES_PRIVATE_SYMBOLS) set_property(TARGET ${LIB_STATIC} APPEND PROPERTY COMPILE_OPTIONS "${CURL_CFLAG_SYMBOLS_HIDE}") set_property(TARGET ${LIB_STATIC} APPEND PROPERTY COMPILE_DEFINITIONS "CURL_HIDDEN_SYMBOLS") @@ -174,6 +173,27 @@ if(BUILD_STATIC_LIBS) target_include_directories(${LIB_STATIC} INTERFACE "$" "$") + + # CMake before CMP0099 (CMake 3.17 2020-03-20) did not propagate libdirs to + # targets. It expected libs to have an absolute filename. As a workaround, + # manually apply dependency libdirs, for CMake consumers without this policy. + if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.17) + cmake_policy(GET CMP0099 _has_CMP0099) # https://cmake.org/cmake/help/latest/policy/CMP0099.html + endif() + if(NOT _has_CMP0099 AND CMAKE_VERSION VERSION_GREATER_EQUAL 3.13 AND CURL_LIBS) + set(_curl_libdirs "") + foreach(_curl_lib IN LISTS CURL_LIBS) + if(TARGET "${_curl_lib}") + get_target_property(_curl_libdir "${_curl_lib}" INTERFACE_LINK_DIRECTORIES) + if(_curl_libdir) + list(APPEND _curl_libdirs "${_curl_libdir}") + endif() + endif() + endforeach() + if(_curl_libdirs) + target_link_directories(${LIB_STATIC} INTERFACE ${_curl_libdirs}) + endif() + endif() endif() if(BUILD_SHARED_LIBS) @@ -304,7 +324,7 @@ add_library(${LIB_NAME} ALIAS ${LIB_SELECTED}) add_library(${PROJECT_NAME}::${LIB_NAME} ALIAS ${LIB_SELECTED}) if(CURL_ENABLE_EXPORT_TARGET) - if(BUILD_STATIC_LIBS) + if(NOT CURL_DISABLE_INSTALL AND BUILD_STATIC_LIBS) install(TARGETS ${LIB_STATIC} EXPORT ${TARGETS_EXPORT_NAME} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} @@ -312,7 +332,7 @@ if(CURL_ENABLE_EXPORT_TARGET) RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ) endif() - if(BUILD_SHARED_LIBS) + if(NOT CURL_DISABLE_INSTALL AND BUILD_SHARED_LIBS) install(TARGETS ${LIB_SHARED} EXPORT ${TARGETS_EXPORT_NAME} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} @@ -326,3 +346,12 @@ if(CURL_ENABLE_EXPORT_TARGET) NAMESPACE ${PROJECT_NAME}:: ) endif() + +if(PERL_EXECUTABLE) + add_custom_target(curl-optiontable + COMMENT "Generating lib/easyoptions.c" VERBATIM USES_TERMINAL + COMMAND "${PERL_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/optiontable.pl" < "${PROJECT_SOURCE_DIR}/include/curl/curl.h" + > "${PROJECT_SOURCE_DIR}/lib/easyoptions.c" + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/optiontable.pl" "${PROJECT_SOURCE_DIR}/include/curl/curl.h" + ) +endif() diff --git a/lib/Makefile.am b/lib/Makefile.am index 784b7f35d61e..833d7566482f 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -26,7 +26,7 @@ AUTOMAKE_OPTIONS = foreign nostdinc # Get CSOURCES, HHEADERS, LIB_RCFILES variables include Makefile.inc -CMAKE_DIST = CMakeLists.txt curl_config.h.cmake +CMAKE_DIST = CMakeLists.txt curl_config-cmake.h.in EXTRA_DIST = config-mac.h config-os400.h config-plan9.h config-riscos.h \ config-win32.h curl_config.h.in $(LIB_RCFILES) libcurl.def \ @@ -63,8 +63,6 @@ AM_CPPFLAGS = -I$(top_srcdir)/include \ # Prevent LIBS from being used for all link targets LIBS = $(BLANK_AT_MAKETIME) -AM_LDFLAGS = -AM_CFLAGS = if DEBUGBUILD AM_CPPFLAGS += -DDEBUGBUILD endif @@ -136,12 +134,11 @@ 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) $(CURL_LDFLAGS_LIB) $(LIBCURL_PC_LIBS_PRIVATE) -libcurl_la_CFLAGS = $(AM_CFLAGS) $(libcurl_la_CFLAGS_EXTRA) +libcurl_la_LDFLAGS = $(libcurl_la_LDFLAGS_EXTRA) $(CURL_LDFLAGS_LIB) $(LIBCURL_PC_LIBS_PRIVATE) +libcurl_la_CFLAGS = $(libcurl_la_CFLAGS_EXTRA) libcurlu_la_CPPFLAGS = $(AM_CPPFLAGS) -DCURL_STATICLIB -DUNITTESTS -libcurlu_la_LDFLAGS = $(AM_LDFLAGS) -static $(LIBCURL_PC_LIBS_PRIVATE) -libcurlu_la_CFLAGS = $(AM_CFLAGS) +libcurlu_la_LDFLAGS = -static $(LIBCURL_PC_LIBS_PRIVATE) CHECKSRC = $(CS_$(V)) CS_0 = @echo " RUN " $@; @@ -168,7 +165,7 @@ UNITV_ = $(UNITV_0) # UNITPROTOS depends on every C file in the lib/ dir $(UNITPROTOS): $(CSOURCES) - $(UNIT_V)(cd $(srcdir) && @PERL@ ../scripts/extract-unit-protos $(CSOURCES) > $(top_builddir)/lib/$(UNITPROTOS)) + $(UNIT_V)(cd $(srcdir) && @PERL@ ../scripts/extract-unit-protos $(CSOURCES)) > $(top_builddir)/lib/$(UNITPROTOS) # disable the tests that are mostly causing false positives TIDYFLAGS := -checks=-clang-analyzer-security.insecureAPI.bzero,-clang-analyzer-security.insecureAPI.strcpy,-clang-analyzer-optin.performance.Padding,-clang-analyzer-security.ArrayBound,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling -quiet diff --git a/lib/Makefile.inc b/lib/Makefile.inc index f06af2ca70e3..402a5be229fb 100644 --- a/lib/Makefile.inc +++ b/lib/Makefile.inc @@ -31,6 +31,7 @@ LIB_CURLX_CFILES = \ curlx/inet_pton.c \ curlx/multibyte.c \ curlx/nonblock.c \ + curlx/strcopy.c \ curlx/strerr.c \ curlx/strparse.c \ curlx/timediff.c \ @@ -50,6 +51,8 @@ LIB_CURLX_HFILES = \ curlx/inet_pton.h \ curlx/multibyte.h \ curlx/nonblock.h \ + curlx/snprintf.h \ + curlx/strcopy.h \ curlx/strerr.h \ curlx/strparse.h \ curlx/timediff.h \ @@ -85,7 +88,6 @@ LIB_VTLS_CFILES = \ vtls/hostcheck.c \ vtls/keylog.c \ vtls/mbedtls.c \ - vtls/mbedtls_threadlock.c \ vtls/openssl.c \ vtls/rustls.c \ vtls/schannel.c \ @@ -103,7 +105,6 @@ LIB_VTLS_HFILES = \ vtls/hostcheck.h \ vtls/keylog.h \ vtls/mbedtls.h \ - vtls/mbedtls_threadlock.h \ vtls/openssl.h \ vtls/rustls.h \ vtls/schannel.h \ @@ -133,10 +134,10 @@ LIB_VQUIC_HFILES = \ LIB_VSSH_CFILES = \ vssh/libssh.c \ vssh/libssh2.c \ - vssh/curl_path.c + vssh/vssh.c LIB_VSSH_HFILES = \ - vssh/curl_path.h \ + vssh/vssh.h \ vssh/ssh.h LIB_CFILES = \ @@ -160,7 +161,6 @@ LIB_CFILES = \ cookie.c \ cshutdn.c \ curl_addrinfo.c \ - curl_des.c \ curl_endian.c \ curl_fnmatch.c \ curl_fopen.c \ @@ -173,6 +173,7 @@ LIB_CFILES = \ curl_rtmp.c \ curl_sasl.c \ curl_sha512_256.c \ + curl_share.c \ curl_sspi.c \ curl_threads.c \ curl_trc.c \ @@ -235,14 +236,13 @@ LIB_CFILES = \ progress.c \ psl.c \ rand.c \ - rename.c \ + ratelimit.c \ request.c \ rtsp.c \ select.c \ sendf.c \ setopt.c \ sha256.c \ - share.c \ slist.c \ smb.c \ smtp.c \ @@ -250,7 +250,6 @@ LIB_CFILES = \ socks.c \ socks_gssapi.c \ socks_sspi.c \ - speedcheck.c \ splay.c \ strcase.c \ strdup.c \ @@ -290,7 +289,6 @@ LIB_HFILES = \ cookie.h \ curl_addrinfo.h \ curl_ctype.h \ - curl_des.h \ curl_endian.h \ curl_fnmatch.h \ curl_fopen.h \ @@ -301,8 +299,6 @@ LIB_HFILES = \ curl_ldap.h \ curl_md4.h \ curl_md5.h \ - curl_mem_undef.h \ - curl_memory.h \ curl_memrchr.h \ curl_ntlm_core.h \ curl_printf.h \ @@ -313,6 +309,7 @@ LIB_HFILES = \ curl_setup_once.h \ curl_sha256.h \ curl_sha512_256.h \ + curl_share.h \ curl_sspi.h \ curl_threads.h \ curl_trc.h \ @@ -353,7 +350,6 @@ LIB_HFILES = \ imap.h \ llist.h \ macos.h \ - memdebug.h \ mime.h \ mqtt.h \ multihandle.h \ @@ -368,7 +364,7 @@ LIB_HFILES = \ progress.h \ psl.h \ rand.h \ - rename.h \ + ratelimit.h \ request.h \ rtsp.h \ select.h \ @@ -377,7 +373,6 @@ LIB_HFILES = \ setup-os400.h \ setup-vms.h \ setup-win32.h \ - share.h \ sigpipe.h \ slist.h \ smb.h \ @@ -385,7 +380,6 @@ LIB_HFILES = \ sockaddr.h \ socketpair.h \ socks.h \ - speedcheck.h \ splay.h \ strcase.h \ strdup.h \ diff --git a/lib/altsvc.c b/lib/altsvc.c index 449bea8528dc..b4bb875438f9 100644 --- a/lib/altsvc.c +++ b/lib/altsvc.c @@ -28,25 +28,18 @@ #include "curl_setup.h" #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_ALTSVC) -#include #include "urldata.h" #include "altsvc.h" #include "curl_fopen.h" #include "curl_get_line.h" #include "parsedate.h" -#include "sendf.h" -#include "curlx/warnless.h" -#include "rename.h" -#include "strdup.h" +#include "curl_trc.h" #include "curlx/inet_pton.h" #include "curlx/strparse.h" +#include "curlx/timeval.h" #include "connect.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - -#define MAX_ALTSVC_LINE 4095 +#define MAX_ALTSVC_LINE 4095 #define MAX_ALTSVC_DATELEN 256 #define MAX_ALTSVC_HOSTLEN 2048 #define MAX_ALTSVC_ALPNLEN 10 @@ -68,13 +61,7 @@ const char *Curl_alpnid2str(enum alpnid id) } } - -static void altsvc_free(struct altsvc *as) -{ - free(as->src.host); - free(as->dst.host); - free(as); -} +#define altsvc_free(x) curlx_free(x) static struct altsvc *altsvc_createid(const char *srchost, size_t hlen, @@ -85,38 +72,35 @@ static struct altsvc *altsvc_createid(const char *srchost, size_t srcport, size_t dstport) { - struct altsvc *as = calloc(1, sizeof(struct altsvc)); - if(!as) - return NULL; - DEBUGASSERT(hlen); - DEBUGASSERT(dlen); - if(!hlen || !dlen) - /* bad input */ - goto error; + struct altsvc *as; if((hlen > 2) && srchost[0] == '[') { /* IPv6 address, strip off brackets */ srchost++; hlen -= 2; } - else if(srchost[hlen - 1] == '.') { + else if(hlen && (srchost[hlen - 1] == '.')) { /* strip off trailing dot */ hlen--; - if(!hlen) - goto error; } if((dlen > 2) && dsthost[0] == '[') { /* IPv6 address, strip off brackets */ dsthost++; dlen -= 2; } + if(!hlen || !dlen) + /* bad input */ + return NULL; + /* struct size plus both strings */ + as = curlx_calloc(1, sizeof(struct altsvc) + (hlen + 1) + (dlen + 1)); + if(!as) + return NULL; + as->src.host = (char *)as + sizeof(struct altsvc); + memcpy(as->src.host, srchost, hlen); + /* the null terminator is already there */ - as->src.host = Curl_memdup0(srchost, hlen); - if(!as->src.host) - goto error; - - as->dst.host = Curl_memdup0(dsthost, dlen); - if(!as->dst.host) - goto error; + as->dst.host = (char *)as + sizeof(struct altsvc) + hlen + 1; + memcpy(as->dst.host, dsthost, dlen); + /* the null terminator is already there */ as->src.alpnid = srcalpnid; as->dst.alpnid = dstalpnid; @@ -124,9 +108,6 @@ static struct altsvc *altsvc_createid(const char *srchost, as->dst.port = (unsigned short)dstport; return as; -error: - altsvc_free(as); - return NULL; } static struct altsvc *altsvc_create(struct Curl_str *srchost, @@ -136,10 +117,8 @@ static struct altsvc *altsvc_create(struct Curl_str *srchost, size_t srcport, size_t dstport) { - enum alpnid dstalpnid = - Curl_alpn2alpnid(curlx_str(dstalpn), curlx_strlen(dstalpn)); - enum alpnid srcalpnid = - Curl_alpn2alpnid(curlx_str(srcalpn), curlx_strlen(srcalpn)); + enum alpnid dstalpnid = Curl_str2alpnid(dstalpn); + enum alpnid srcalpnid = Curl_str2alpnid(srcalpn); if(!srcalpnid || !dstalpnid) return NULL; return altsvc_createid(curlx_str(srchost), curlx_strlen(srchost), @@ -201,6 +180,8 @@ static CURLcode altsvc_add(struct altsvcinfo *asi, const char *line) as->persist = persist ? 1 : 0; Curl_llist_append(&asi->list, as, &as->node); } + else + return CURLE_OUT_OF_MEMORY; } return CURLE_OK; @@ -221,21 +202,25 @@ static CURLcode altsvc_load(struct altsvcinfo *asi, const char *file) /* we need a private copy of the filename so that the altsvc cache file name survives an easy handle reset */ - free(asi->filename); - asi->filename = strdup(file); + curlx_free(asi->filename); + asi->filename = curlx_strdup(file); if(!asi->filename) return CURLE_OUT_OF_MEMORY; fp = curlx_fopen(file, FOPEN_READTEXT); if(fp) { + bool eof = FALSE; struct dynbuf buf; curlx_dyn_init(&buf, MAX_ALTSVC_LINE); - while(Curl_get_line(&buf, fp)) { - const char *lineptr = curlx_dyn_ptr(&buf); - curlx_str_passblanks(&lineptr); - if(curlx_str_single(&lineptr, '#')) - altsvc_add(asi, lineptr); - } + do { + result = Curl_get_line(&buf, fp, &eof); + if(!result) { + const char *lineptr = curlx_dyn_ptr(&buf); + curlx_str_passblanks(&lineptr); + if(curlx_str_single(&lineptr, '#')) + altsvc_add(asi, lineptr); + } + } while(!result && !eof); curlx_dyn_free(&buf); /* free the line buffer */ curlx_fclose(fp); } @@ -253,7 +238,7 @@ static CURLcode altsvc_out(struct altsvc *as, FILE *fp) const char *dst6_post = ""; const char *src6_pre = ""; const char *src6_post = ""; - CURLcode result = Curl_gmtime(as->expires, &stamp); + CURLcode result = curlx_gmtime(as->expires, &stamp); if(result) return result; #ifdef USE_IPV6 @@ -297,7 +282,7 @@ static CURLcode altsvc_out(struct altsvc *as, FILE *fp) */ struct altsvcinfo *Curl_altsvc_init(void) { - struct altsvcinfo *asi = calloc(1, sizeof(struct altsvcinfo)); + struct altsvcinfo *asi = curlx_calloc(1, sizeof(struct altsvcinfo)); if(!asi) return NULL; Curl_llist_init(&asi->list, NULL); @@ -348,8 +333,8 @@ void Curl_altsvc_cleanup(struct altsvcinfo **altsvcp) n = Curl_node_next(e); altsvc_free(as); } - free(altsvc->filename); - free(altsvc); + curlx_free(altsvc->filename); + curlx_free(altsvc); *altsvcp = NULL; /* clear the pointer */ } } @@ -391,13 +376,13 @@ CURLcode Curl_altsvc_save(struct Curl_easy *data, break; } curlx_fclose(out); - if(!result && tempstore && Curl_rename(tempstore, file)) + if(!result && tempstore && curlx_rename(tempstore, file)) result = CURLE_WRITE_ERROR; if(result && tempstore) unlink(tempstore); } - free(tempstore); + curlx_free(tempstore); return result; } @@ -541,8 +526,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data, do { if(!curlx_str_single(&p, '=')) { /* [protocol]="[host][:port], [protocol]="[host][:port]" */ - enum alpnid dstalpnid = - Curl_alpn2alpnid(curlx_str(&alpn), curlx_strlen(&alpn)); + enum alpnid dstalpnid = Curl_str2alpnid(&alpn); if(!curlx_str_single(&p, '\"')) { struct Curl_str dsthost; curl_off_t port = 0; @@ -555,7 +539,7 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data, } } else { - /* IPv6 host name */ + /* IPv6 hostname */ if(curlx_str_until(&p, &dsthost, MAX_IPADR_LEN, ']') || curlx_str_single(&p, ']')) { infof(data, "Bad alt-svc IPv6 hostname, ignoring."); @@ -604,6 +588,8 @@ CURLcode Curl_altsvc_parse(struct Curl_easy *data, (int)curlx_strlen(&dsthost), curlx_str(&dsthost), dstport, Curl_alpnid2str(dstalpnid)); } + else + return CURLE_OUT_OF_MEMORY; } } else @@ -633,7 +619,8 @@ bool Curl_altsvc_lookup(struct altsvcinfo *asi, enum alpnid srcalpnid, const char *srchost, int srcport, struct altsvc **dstentry, - const int versions) /* one or more bits */ + const int versions, /* one or more bits */ + bool *psame_destination) { struct Curl_llist_node *e; struct Curl_llist_node *n; @@ -642,6 +629,7 @@ bool Curl_altsvc_lookup(struct altsvcinfo *asi, DEBUGASSERT(srchost); DEBUGASSERT(dstentry); + *psame_destination = FALSE; for(e = Curl_llist_head(&asi->list); e; e = n) { struct altsvc *as = Curl_node_elem(e); n = Curl_node_next(e); @@ -657,6 +645,8 @@ bool Curl_altsvc_lookup(struct altsvcinfo *asi, (versions & (int)as->dst.alpnid)) { /* match */ *dstentry = as; + *psame_destination = (srcport == as->dst.port) && + hostcompare(srchost, as->dst.host); return TRUE; } } diff --git a/lib/altsvc.h b/lib/altsvc.h index 831cd097436a..b82eaa8f717d 100644 --- a/lib/altsvc.h +++ b/lib/altsvc.h @@ -26,7 +26,6 @@ #include "curl_setup.h" #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_ALTSVC) -#include #include "llist.h" struct althost { @@ -65,10 +64,11 @@ bool Curl_altsvc_lookup(struct altsvcinfo *asi, enum alpnid srcalpnid, const char *srchost, int srcport, struct altsvc **dstentry, - const int versions); /* CURLALTSVC_H* bits */ + const int versions, /* CURLALTSVC_H* bits */ + bool *psame_destination); #else /* disabled */ -#define Curl_altsvc_save(a,b,c) +#define Curl_altsvc_save(a, b, c) #define Curl_altsvc_cleanup(x) #endif /* !CURL_DISABLE_HTTP && !CURL_DISABLE_ALTSVC */ #endif /* HEADER_CURL_ALTSVC_H */ diff --git a/lib/amigaos.c b/lib/amigaos.c index e51236d1260a..76d67b08fea4 100644 --- a/lib/amigaos.c +++ b/lib/amigaos.c @@ -26,13 +26,11 @@ #ifdef __AMIGA__ -#include - #include "hostip.h" #include "amigaos.h" #ifdef HAVE_PROTO_BSDSOCKET_H -# if defined(__amigaos4__) +# ifdef __amigaos4__ # include # elif !defined(USE_AMISSL) # include @@ -42,10 +40,6 @@ # endif #endif -/* The last #include files should be: */ -#include "curl_memory.h" -#include "memdebug.h" - #ifdef HAVE_PROTO_BSDSOCKET_H #ifdef __amigaos4__ @@ -120,12 +114,11 @@ void Curl_amiga_cleanup(void) * Because we need to handle the different cases in hostip4.c at runtime, * not at compile-time, based on what was detected in Curl_amiga_init(), * we replace it completely with our own as to not complicate the baseline - * code. Assumes malloc/calloc/free are thread safe because Curl_he2ai() + * code. Assumes malloc/calloc/free are thread-safe because Curl_he2ai() * allocates memory also. */ -struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, - int port) +struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port) { struct Curl_addrinfo *ai = NULL; struct hostent *h; @@ -135,7 +128,7 @@ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, LONG h_errnop = 0; struct hostent *buf; - buf = calloc(1, CURL_HOSTENT_SIZE); + buf = curlx_calloc(1, CURL_HOSTENT_SIZE); if(buf) { h = gethostbyname_r((STRPTR)hostname, buf, (char *)buf + sizeof(struct hostent), @@ -144,12 +137,12 @@ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, if(h) { ai = Curl_he2ai(h, port); } - free(buf); + curlx_free(buf); } } else { - #ifdef CURLRES_THREADED - /* gethostbyname() is not thread safe, so we need to reopen bsdsocket +#ifdef CURLRES_THREADED + /* gethostbyname() is not thread-safe, so we need to reopen bsdsocket * on the thread's context */ struct Library *base = OpenLibrary("bsdsocket.library", 4); @@ -164,13 +157,13 @@ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, } CloseLibrary(base); } - #else +#else /* not using threaded resolver - safe to use this as-is */ h = gethostbyname(hostname); if(h) { ai = Curl_he2ai(h, port); } - #endif +#endif } return ai; @@ -223,8 +216,7 @@ CURLcode Curl_amiga_init(void) } if(SocketBaseTags(SBTM_SETVAL(SBTC_ERRNOPTR(sizeof(errno))), (ULONG)&errno, - SBTM_SETVAL(SBTC_LOGTAGPTR), (ULONG)"curl", - TAG_DONE)) { + SBTM_SETVAL(SBTC_LOGTAGPTR), (ULONG)"curl", TAG_DONE)) { CURL_AMIGA_REQUEST("SocketBaseTags ERROR"); return CURLE_FAILED_INIT; } diff --git a/lib/amigaos.h b/lib/amigaos.h index c99d963ececc..58278f093561 100644 --- a/lib/amigaos.h +++ b/lib/amigaos.h @@ -33,7 +33,7 @@ void Curl_amiga_cleanup(void); #else -#define Curl_amiga_init() CURLE_OK +#define Curl_amiga_init() CURLE_OK #define Curl_amiga_cleanup() Curl_nop_stmt #endif diff --git a/lib/arpa_telnet.h b/lib/arpa_telnet.h index d641a01da819..daf2487fc616 100644 --- a/lib/arpa_telnet.h +++ b/lib/arpa_telnet.h @@ -43,8 +43,7 @@ /* * The telnet options represented as strings */ -static const char * const telnetoptions[]= -{ +static const char * const telnetoptions[] = { "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME", "STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP", "NAOCRD", "NAOHTS", @@ -79,15 +78,14 @@ static const char * const telnetoptions[]= #define CURL_WILL 251 /* Our side WILL use this option */ #define CURL_WONT 252 /* Our side will not use this option */ #define CURL_DO 253 /* DO use this option! */ -#define CURL_DONT 254 /* DON'T use this option! */ +#define CURL_DONT 254 /* DO NOT use this option! */ #define CURL_IAC 255 /* Interpret As Command */ #ifndef CURL_DISABLE_VERBOSE_STRINGS /* * Then those numbers represented as strings: */ -static const char * const telnetcmds[]= -{ +static const char * const telnetcmds[] = { "EOF", "SUSP", "ABORT", "EOR", "SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC", "EL", "GA", "SB", @@ -103,11 +101,11 @@ static const char * const telnetcmds[]= #define CURL_TELQUAL_INFO 2 #define CURL_TELQUAL_NAME 3 -#define CURL_TELCMD_OK(x) ( ((unsigned int)(x) >= CURL_TELCMD_MINIMUM) && \ - ((unsigned int)(x) <= CURL_TELCMD_MAXIMUM) ) +#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] +#define CURL_TELCMD(x) telnetcmds[(x) - CURL_TELCMD_MINIMUM] #else #define CURL_TELCMD(x) "" #endif diff --git a/lib/asyn-ares.c b/lib/asyn-ares.c index 040100acec36..d723de987366 100644 --- a/lib/asyn-ares.c +++ b/lib/asyn-ares.c @@ -32,7 +32,6 @@ * as defined in asyn.h, nothing else belongs in this file! **********************************************************************/ -#include #ifdef HAVE_NETINET_IN_H #include #endif @@ -49,10 +48,8 @@ #include "urldata.h" #include "cfilters.h" -#include "sendf.h" +#include "curl_trc.h" #include "hostip.h" -#include "hash.h" -#include "share.h" #include "url.h" #include "multiif.h" #include "curlx/inet_pton.h" @@ -61,7 +58,6 @@ #include "progress.h" #include "curlx/timediff.h" #include "httpsrr.h" -#include "strdup.h" #include #include /* really old c-ares did not include this by @@ -89,7 +85,7 @@ /* How long we are willing to wait for additional parallel responses after obtaining a "definitive" one. For old c-ares without getaddrinfo. - This is intended to equal the c-ares default timeout. cURL always uses that + This is intended to equal the c-ares default timeout. curl always uses that default value. Unfortunately, c-ares does not expose its default timeout in its API, but it is officially documented as 5 seconds. @@ -105,10 +101,6 @@ #define HTTPSRR_WORKS #endif -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - #define CARES_TIMEOUT_PER_ATTEMPT 2000 static int ares_ver = 0; @@ -145,7 +137,6 @@ void Curl_async_global_cleanup(void) #endif } - static void sock_state_cb(void *data, ares_socket_t socket_fd, int readable, int writable) { @@ -186,8 +177,7 @@ static CURLcode async_ares_init(struct Curl_easy *data) status = ares_init_options(&ares->channel, &options, optmask); if(status != ARES_SUCCESS) { ares->channel = NULL; - rc = (status == ARES_ENOMEM) ? - CURLE_OUT_OF_MEMORY : CURLE_FAILED_INIT; + rc = (status == ARES_ENOMEM) ? CURLE_OUT_OF_MEMORY : CURLE_FAILED_INIT; goto out; } @@ -314,12 +304,13 @@ CURLcode Curl_async_is_resolved(struct Curl_easy *data, /* Now that we have checked for any last minute results above, see if there are any responses still pending when the EXPIRE_HAPPY_EYEBALLS_DNS timer expires. */ - if(ares->num_pending + if(ares->num_pending && /* This is only set to non-zero if the timer was started. */ - && (ares->happy_eyeballs_dns_time.tv_sec - || ares->happy_eyeballs_dns_time.tv_usec) - && (curlx_timediff(curlx_now(), ares->happy_eyeballs_dns_time) - >= HAPPY_EYEBALLS_DNS_TIMEOUT)) { + (ares->happy_eyeballs_dns_time.tv_sec || + ares->happy_eyeballs_dns_time.tv_usec) && + (curlx_ptimediff_ms(Curl_pgrs_now(data), + &ares->happy_eyeballs_dns_time) >= + HAPPY_EYEBALLS_DNS_TIMEOUT)) { /* Remember that the EXPIRE_HAPPY_EYEBALLS_DNS timer is no longer running. */ memset(&ares->happy_eyeballs_dns_time, 0, @@ -344,7 +335,8 @@ CURLcode Curl_async_is_resolved(struct Curl_easy *data, Curl_dnscache_mk_entry(data, ares->temp_ai, data->state.async.hostname, 0, data->state.async.port, FALSE); - ares->temp_ai = NULL; /* temp_ai now owned by entry */ + if(data->state.async.dns) + ares->temp_ai = NULL; /* temp_ai now owned by entry */ #ifdef HTTPSRR_WORKS if(data->state.async.dns) { struct Curl_https_rrinfo *lhrr = Curl_httpsrr_dup_move(&ares->hinfo); @@ -395,47 +387,46 @@ CURLcode Curl_async_await(struct Curl_easy *data, { struct async_ares_ctx *ares = &data->state.async.ares; CURLcode result = CURLE_OK; - timediff_t timeout; - struct curltime now = curlx_now(); + timediff_t timeout_ms; DEBUGASSERT(entry); *entry = NULL; /* clear on entry */ - timeout = Curl_timeleft(data, &now, TRUE); - if(timeout < 0) { + timeout_ms = Curl_timeleft_ms(data, TRUE); + if(timeout_ms < 0) { /* already expired! */ connclose(data->conn, "Timed out before name resolve started"); return CURLE_OPERATION_TIMEDOUT; } - if(!timeout) - timeout = CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve timeout */ + if(!timeout_ms) + timeout_ms = CURL_TIMEOUT_RESOLVE * 1000; /* default name resolve */ /* Wait for the name resolve query to complete. */ while(!result) { - struct timeval *tvp, tv, store; - int itimeout; - timediff_t timeout_ms; + struct timeval *real_timeout, time_buf, max_timeout; + int itimeout_ms; + timediff_t call_timeout_ms; #if TIMEDIFF_T_MAX > INT_MAX - itimeout = (timeout > INT_MAX) ? INT_MAX : (int)timeout; + itimeout_ms = (timeout_ms > INT_MAX) ? INT_MAX : (int)timeout_ms; #else - itimeout = (int)timeout; + itimeout_ms = (int)timeout_ms; #endif - store.tv_sec = itimeout/1000; - store.tv_usec = (itimeout%1000)*1000; + max_timeout.tv_sec = itimeout_ms / 1000; + max_timeout.tv_usec = (itimeout_ms % 1000) * 1000; - tvp = ares_timeout(ares->channel, &store, &tv); + real_timeout = ares_timeout(ares->channel, &max_timeout, &time_buf); /* use the timeout period ares returned to us above if less than one second is left, otherwise just use 1000ms to make sure the progress callback gets called frequent enough */ - if(!tvp->tv_sec) - timeout_ms = (timediff_t)(tvp->tv_usec/1000); + if(!real_timeout->tv_sec) + call_timeout_ms = (timediff_t)(real_timeout->tv_usec / 1000); else - timeout_ms = 1000; + call_timeout_ms = 1000; - if(Curl_ares_perform(ares->channel, timeout_ms) < 0) + if(Curl_ares_perform(ares->channel, call_timeout_ms) < 0) return CURLE_UNRECOVERABLE_POLL; result = Curl_async_is_resolved(data, entry); @@ -445,17 +436,16 @@ CURLcode Curl_async_await(struct Curl_easy *data, if(Curl_pgrsUpdate(data)) result = CURLE_ABORTED_BY_CALLBACK; else { - struct curltime now2 = curlx_now(); - timediff_t timediff = curlx_timediff(now2, now); /* spent time */ - if(timediff <= 0) - timeout -= 1; /* always deduct at least 1 */ - else if(timediff > timeout) - timeout = -1; + struct curltime now = curlx_now(); /* update in loop */ + timediff_t elapsed_ms = curlx_ptimediff_ms(&now, Curl_pgrs_now(data)); + if(elapsed_ms <= 0) + timeout_ms -= 1; /* always deduct at least 1 */ + else if(elapsed_ms > timeout_ms) + timeout_ms = -1; else - timeout -= timediff; - now = now2; /* for next loop */ + timeout_ms -= elapsed_ms; } - if(timeout < 0) + if(timeout_ms < 0) result = CURLE_OPERATION_TIMEDOUT; } @@ -522,7 +512,7 @@ static void async_ares_hostbyname_cb(void *user_data, if(ARES_SUCCESS == status) { ares->ares_status = status; /* one success overrules any error */ async_addr_concat(&ares->temp_ai, - Curl_he2ai(hostent, data->state.async.port)); + Curl_he2ai(hostent, data->state.async.port)); } else if(ares->ares_status != ARES_SUCCESS) { /* no success so far, remember last error */ @@ -567,7 +557,7 @@ static void async_ares_hostbyname_cb(void *user_data, So, now that we have a usable answer (some IPv4 addresses, some IPv6 addresses, or "no such domain"), we start a timeout for the remaining pending responses. Even though it is typical that this resolved - request came back quickly, that needn't be the case. It might be that + request came back quickly, that need not be the case. It might be that this completing request did not get a result from the first DNS server or even the first round of the whole DNS server pool. So it could already be quite some time after we issued the DNS queries in @@ -589,9 +579,8 @@ static void async_ares_hostbyname_cb(void *user_data, timeout to prevent it. After all, we do not even know where in the c-ares retry cycle each request is. */ - ares->happy_eyeballs_dns_time = curlx_now(); - Curl_expire(data, HAPPY_EYEBALLS_DNS_TIMEOUT, - EXPIRE_HAPPY_EYEBALLS_DNS); + ares->happy_eyeballs_dns_time = *Curl_pgrs_now(data); + Curl_expire(data, HAPPY_EYEBALLS_DNS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS_DNS); } } @@ -633,7 +622,7 @@ async_ares_node2addr(struct ares_addrinfo_node *node) if((size_t)ai->ai_addrlen < ss_size) continue; - ca = malloc(sizeof(struct Curl_addrinfo) + ss_size); + ca = curlx_malloc(sizeof(struct Curl_addrinfo) + ss_size); if(!ca) { error = EAI_MEMORY; break; @@ -719,30 +708,33 @@ static void async_ares_rr_done(void *user_data, ares_status_t status, /* * Curl_async_getaddrinfo() - when using ares * - * Returns name information about the given hostname and port number. If - * successful, the 'hostent' is returned and the fourth argument will point to - * memory we need to free after use. That memory *MUST* be freed with - * Curl_freeaddrinfo(), nothing else. + * Starts a name resolve for the given hostname and port number. */ -struct Curl_addrinfo *Curl_async_getaddrinfo(struct Curl_easy *data, - const char *hostname, - int port, - int ip_version, - int *waitp) +CURLcode Curl_async_getaddrinfo(struct Curl_easy *data, const char *hostname, + int port, int ip_version) { struct async_ares_ctx *ares = &data->state.async.ares; - *waitp = 0; /* default to synchronous response */ +#ifdef USE_HTTPSRR + char *rrname = NULL; +#endif if(async_ares_init_lazy(data)) - return NULL; + return CURLE_FAILED_INIT; data->state.async.done = FALSE; /* not done */ data->state.async.dns = NULL; /* clear */ data->state.async.port = port; data->state.async.ip_version = ip_version; - data->state.async.hostname = strdup(hostname); + data->state.async.hostname = curlx_strdup(hostname); if(!data->state.async.hostname) - return NULL; + return CURLE_OUT_OF_MEMORY; +#ifdef USE_HTTPSRR + if(port != 443) { + rrname = curl_maprintf("_%d_.https.%s", port, hostname); + if(!rrname) + return CURLE_OUT_OF_MEMORY; + } +#endif /* initial status - failed */ ares->ares_status = ARES_ENOTFOUND; @@ -815,18 +807,20 @@ struct Curl_addrinfo *Curl_async_getaddrinfo(struct Curl_easy *data, #endif #ifdef USE_HTTPSRR { - CURL_TRC_DNS(data, "asyn-ares: fire off query for HTTPSRR"); + CURL_TRC_DNS(data, "asyn-ares: fire off query for HTTPSRR: %s", + rrname ? rrname : data->state.async.hostname); memset(&ares->hinfo, 0, sizeof(ares->hinfo)); ares->hinfo.port = -1; + ares->hinfo.rrname = rrname; ares->num_pending++; /* one more */ - ares_query_dnsrec(ares->channel, data->state.async.hostname, + ares_query_dnsrec(ares->channel, + rrname ? rrname : data->state.async.hostname, ARES_CLASS_IN, ARES_REC_TYPE_HTTPS, async_ares_rr_done, data, NULL); } #endif - *waitp = 1; /* expect asynchronous response */ - return NULL; /* no struct yet */ + return CURLE_OK; } /* Set what DNS server are is to use. This is called in 2 situations: diff --git a/lib/asyn-base.c b/lib/asyn-base.c index eb2240b816c9..398e41dffd0b 100644 --- a/lib/asyn-base.c +++ b/lib/asyn-base.c @@ -46,23 +46,16 @@ #include "urldata.h" #include "asyn.h" -#include "sendf.h" #include "hostip.h" -#include "hash.h" #include "multiif.h" #include "select.h" -#include "share.h" #include "url.h" -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" /*********************************************************************** * Only for builds using asynchronous name resolves **********************************************************************/ #ifdef CURLRES_ASYNCH - #ifdef USE_ARES #if ARES_VERSION < 0x010600 @@ -77,8 +70,6 @@ * * Returns: sockets-in-use-bitmap */ - - CURLcode Curl_ares_pollset(struct Curl_easy *data, ares_channel channel, struct easy_pollset *ps) @@ -127,8 +118,7 @@ CURLcode Curl_ares_pollset(struct Curl_easy *data, * * return number of sockets it worked on, or -1 on error */ -int Curl_ares_perform(ares_channel channel, - timediff_t timeout_ms) +int Curl_ares_perform(ares_channel channel, timediff_t timeout_ms) { int nfds; int bitmask; @@ -147,11 +137,11 @@ int Curl_ares_perform(ares_channel channel, pfd[i].revents = 0; if(ARES_GETSOCK_READABLE(bitmask, i)) { pfd[i].fd = socks[i]; - pfd[i].events |= POLLRDNORM|POLLIN; + pfd[i].events |= POLLRDNORM | POLLIN; } if(ARES_GETSOCK_WRITABLE(bitmask, i)) { pfd[i].fd = socks[i]; - pfd[i].events |= POLLWRNORM|POLLOUT; + pfd[i].events |= POLLWRNORM | POLLOUT; } if(pfd[i].events) num++; @@ -175,9 +165,9 @@ int Curl_ares_perform(ares_channel channel, /* move through the descriptors and ask for processing on them */ for(i = 0; i < num; i++) ares_process_fd(channel, - (pfd[i].revents & (POLLRDNORM|POLLIN)) ? + (pfd[i].revents & (POLLRDNORM | POLLIN)) ? pfd[i].fd : ARES_SOCKET_BAD, - (pfd[i].revents & (POLLWRNORM|POLLOUT)) ? + (pfd[i].revents & (POLLWRNORM | POLLOUT)) ? pfd[i].fd : ARES_SOCKET_BAD); } return nfds; diff --git a/lib/asyn-thrdd.c b/lib/asyn-thrdd.c index dc13143e245d..64251ae57ee1 100644 --- a/lib/asyn-thrdd.c +++ b/lib/asyn-thrdd.c @@ -45,26 +45,24 @@ #endif #if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) -# include +#include #endif #ifdef HAVE_GETADDRINFO -# define RESOLVER_ENOMEM EAI_MEMORY /* = WSA_NOT_ENOUGH_MEMORY on Windows */ +#define RESOLVER_ENOMEM EAI_MEMORY /* = WSA_NOT_ENOUGH_MEMORY on Windows */ #else -# define RESOLVER_ENOMEM SOCKENOMEM +#define RESOLVER_ENOMEM SOCKENOMEM #endif #include "urldata.h" #include "cfilters.h" -#include "sendf.h" +#include "curl_trc.h" #include "hostip.h" -#include "hash.h" -#include "share.h" #include "url.h" #include "multiif.h" #include "curl_threads.h" +#include "progress.h" #include "select.h" -#include "strdup.h" #ifdef USE_ARES #include @@ -73,10 +71,6 @@ #endif #endif -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - /* * Curl_async_global_init() @@ -137,7 +131,7 @@ static void addr_ctx_unlink(struct async_thrdd_addr_ctx **paddr_ctx, if(destroy) { Curl_mutex_destroy(&addr_ctx->mutx); - free(addr_ctx->hostname); + curlx_free(addr_ctx->hostname); if(addr_ctx->res) Curl_freeaddrinfo(addr_ctx->res); #ifndef CURL_DISABLE_SOCKETPAIR @@ -146,7 +140,7 @@ static void addr_ctx_unlink(struct async_thrdd_addr_ctx **paddr_ctx, #endif wakeup_close(addr_ctx->sock_pair[0]); #endif - free(addr_ctx); + curlx_free(addr_ctx); } *paddr_ctx = NULL; } @@ -157,7 +151,7 @@ addr_ctx_create(struct Curl_easy *data, const char *hostname, int port, const struct addrinfo *hints) { - struct async_thrdd_addr_ctx *addr_ctx = calloc(1, sizeof(*addr_ctx)); + struct async_thrdd_addr_ctx *addr_ctx = curlx_calloc(1, sizeof(*addr_ctx)); if(!addr_ctx) return NULL; @@ -187,7 +181,7 @@ addr_ctx_create(struct Curl_easy *data, /* Copying hostname string because original can be destroyed by parent * thread during gethostbyname execution. */ - addr_ctx->hostname = strdup(hostname); + addr_ctx->hostname = curlx_strdup(hostname); if(!addr_ctx->hostname) goto err_exit; @@ -250,7 +244,6 @@ static CURL_THREAD_RETURN_T CURL_STDCALL getaddrinfo_thread(void *arg) } } #endif - } addr_ctx_unlink(&addr_ctx, NULL); @@ -362,30 +355,40 @@ static void async_thrdd_rr_done(void *user_data, ares_status_t status, thrdd->rr.result = Curl_httpsrr_from_ares(data, dnsrec, &thrdd->rr.hinfo); } -static CURLcode async_rr_start(struct Curl_easy *data) +static CURLcode async_rr_start(struct Curl_easy *data, int port) { struct async_thrdd_ctx *thrdd = &data->state.async.thrdd; int status; + char *rrname = NULL; DEBUGASSERT(!thrdd->rr.channel); + if(port != 443) { + rrname = curl_maprintf("_%d_.https.%s", port, data->conn->host.name); + if(!rrname) + return CURLE_OUT_OF_MEMORY; + } status = ares_init_options(&thrdd->rr.channel, NULL, 0); if(status != ARES_SUCCESS) { thrdd->rr.channel = NULL; + curlx_free(rrname); return CURLE_FAILED_INIT; } #ifdef CURLDEBUG if(getenv("CURL_DNS_SERVER")) { const char *servers = getenv("CURL_DNS_SERVER"); status = ares_set_servers_ports_csv(thrdd->rr.channel, servers); - if(status) + if(status) { + curlx_free(rrname); return CURLE_FAILED_INIT; + } } #endif memset(&thrdd->rr.hinfo, 0, sizeof(thrdd->rr.hinfo)); thrdd->rr.hinfo.port = -1; + thrdd->rr.hinfo.rrname = rrname; ares_query_dnsrec(thrdd->rr.channel, - data->conn->host.name, ARES_CLASS_IN, + rrname ? rrname : data->conn->host.name, ARES_CLASS_IN, ARES_REC_TYPE_HTTPS, async_thrdd_rr_done, data, NULL); CURL_TRC_DNS(data, "Issued HTTPS-RR request for %s", data->conn->host.name); @@ -426,8 +429,8 @@ static bool async_thrdd_init(struct Curl_easy *data, data->state.async.done = FALSE; data->state.async.port = port; data->state.async.ip_version = ip_version; - free(data->state.async.hostname); - data->state.async.hostname = strdup(hostname); + curlx_free(data->state.async.hostname); + data->state.async.hostname = curlx_strdup(hostname); if(!data->state.async.hostname) goto err_exit; @@ -438,7 +441,7 @@ static bool async_thrdd_init(struct Curl_easy *data, /* passing addr_ctx to the thread adds a reference */ addr_ctx->ref_count = 2; - addr_ctx->start = curlx_now(); + addr_ctx->start = *Curl_pgrs_now(data); #ifdef HAVE_GETADDRINFO addr_ctx->thread_hnd = Curl_thread_create(getaddrinfo_thread, addr_ctx); @@ -455,7 +458,7 @@ static bool async_thrdd_init(struct Curl_easy *data, } #ifdef USE_HTTPSRR_ARES - if(async_rr_start(data)) + if(async_rr_start(data, port)) infof(data, "Failed HTTPS RR operation"); #endif CURL_TRC_DNS(data, "resolve thread started for of %s:%d", hostname, port); @@ -464,7 +467,7 @@ static bool async_thrdd_init(struct Curl_easy *data, err_exit: CURL_TRC_DNS(data, "resolve thread failed init: %d", err); async_thrdd_destroy(data); - CURL_SETERRNO(err); + errno = err; return FALSE; } @@ -481,8 +484,8 @@ static void async_thrdd_shutdown(struct Curl_easy *data) Curl_mutex_acquire(&addr_ctx->mutx); #ifndef CURL_DISABLE_SOCKETPAIR - if(!addr_ctx->do_abort) - Curl_multi_will_close(data, addr_ctx->sock_pair[0]); + if(!addr_ctx->do_abort) + Curl_multi_will_close(data, addr_ctx->sock_pair[0]); #endif addr_ctx->do_abort = TRUE; done = addr_ctx->thrd_done; @@ -651,8 +654,8 @@ CURLcode Curl_async_is_resolved(struct Curl_easy *data, else { /* poll for name lookup done with exponential backoff up to 250ms */ /* should be fine even if this converts to 32-bit */ - timediff_t elapsed = curlx_timediff(curlx_now(), - data->progress.t_startsingle); + timediff_t elapsed = curlx_ptimediff_ms(Curl_pgrs_now(data), + &data->progress.t_startsingle); if(elapsed < 0) elapsed = 0; @@ -660,7 +663,7 @@ CURLcode Curl_async_is_resolved(struct Curl_easy *data, /* Start at 1ms poll interval */ thrdd->addr->poll_interval = 1; else if(elapsed >= thrdd->addr->interval_end) - /* Back-off exponentially if last interval expired */ + /* Back-off exponentially if last interval expired */ thrdd->addr->poll_interval *= 2; if(thrdd->addr->poll_interval > 250) @@ -698,15 +701,16 @@ CURLcode Curl_async_pollset(struct Curl_easy *data, struct easy_pollset *ps) if(!thrd_done) { #ifndef CURL_DISABLE_SOCKETPAIR - /* return read fd to client for polling the DNS resolution status */ + /* return read fd to client for polling the DNS resolution status */ result = Curl_pollset_add_in(data, ps, thrdd->addr->sock_pair[0]); #else timediff_t milli; - timediff_t ms = curlx_timediff(curlx_now(), thrdd->addr->start); + timediff_t ms = + curlx_ptimediff_ms(Curl_pgrs_now(data), &thrdd->addr->start); if(ms < 3) milli = 0; else if(ms <= 50) - milli = ms/3; + milli = ms / 3; else if(ms <= 250) milli = 50; else @@ -721,24 +725,18 @@ CURLcode Curl_async_pollset(struct Curl_easy *data, struct easy_pollset *ps) /* * Curl_async_getaddrinfo() - for platforms without getaddrinfo */ -struct Curl_addrinfo *Curl_async_getaddrinfo(struct Curl_easy *data, - const char *hostname, - int port, - int ip_version, - int *waitp) +CURLcode Curl_async_getaddrinfo(struct Curl_easy *data, const char *hostname, + int port, int ip_version) { (void)ip_version; - *waitp = 0; /* default to synchronous response */ /* fire up a new resolver thread! */ if(async_thrdd_init(data, hostname, port, ip_version, NULL)) { - *waitp = 1; /* expect asynchronous response */ - return NULL; + return CURLE_OK; } failf(data, "getaddrinfo() thread failed"); - - return NULL; + return CURLE_FAILED_INIT; } #else /* !HAVE_GETADDRINFO */ @@ -746,15 +744,11 @@ struct Curl_addrinfo *Curl_async_getaddrinfo(struct Curl_easy *data, /* * Curl_async_getaddrinfo() - for getaddrinfo */ -struct Curl_addrinfo *Curl_async_getaddrinfo(struct Curl_easy *data, - const char *hostname, - int port, - int ip_version, - int *waitp) +CURLcode Curl_async_getaddrinfo(struct Curl_easy *data, const char *hostname, + int port, int ip_version) { struct addrinfo hints; int pf = PF_INET; - *waitp = 0; /* default to synchronous response */ CURL_TRC_DNS(data, "init threaded resolve of %s:%d", hostname, port); #ifdef CURLRES_IPV6 @@ -776,14 +770,11 @@ struct Curl_addrinfo *Curl_async_getaddrinfo(struct Curl_easy *data, SOCK_STREAM : SOCK_DGRAM; /* fire up a new resolver thread! */ - if(async_thrdd_init(data, hostname, port, ip_version, &hints)) { - *waitp = 1; /* expect asynchronous response */ - return NULL; - } + if(async_thrdd_init(data, hostname, port, ip_version, &hints)) + return CURLE_OK; failf(data, "getaddrinfo() thread failed to start"); - return NULL; - + return CURLE_FAILED_INIT; } #endif /* !HAVE_GETADDRINFO */ diff --git a/lib/asyn.h b/lib/asyn.h index 7863042bbe37..87c6532a3d9d 100644 --- a/lib/asyn.h +++ b/lib/asyn.h @@ -118,11 +118,8 @@ CURLcode Curl_async_await(struct Curl_easy *data, * Each resolver backend must of course make sure to return data in the * correct format to comply with this. */ -struct Curl_addrinfo *Curl_async_getaddrinfo(struct Curl_easy *data, - const char *hostname, - int port, - int ip_version, - int *waitp); +CURLcode Curl_async_getaddrinfo(struct Curl_easy *data, const char *hostname, + int port, int ip_version); #ifdef USE_ARES /* common functions for c-ares and threaded resolver with HTTPSRR */ @@ -132,19 +129,18 @@ CURLcode Curl_ares_pollset(struct Curl_easy *data, ares_channel channel, struct easy_pollset *ps); -int Curl_ares_perform(ares_channel channel, - timediff_t timeout_ms); +int Curl_ares_perform(ares_channel channel, timediff_t timeout_ms); #endif #ifdef CURLRES_ARES /* async resolving implementation using c-ares alone */ struct async_ares_ctx { ares_channel channel; - int num_pending; /* number of outstanding c-ares requests */ + int num_pending; /* number of outstanding c-ares requests */ struct Curl_addrinfo *temp_ai; /* intermediary result while fetching c-ares parts */ - int ares_status; /* ARES_SUCCESS, ARES_ENOTFOUND, etc. */ - CURLcode result; /* CURLE_OK or error handling response */ + int ares_status; /* ARES_SUCCESS, ARES_ENOTFOUND, etc. */ + CURLcode result; /* CURLE_OK or error handling response */ #ifndef HAVE_CARES_GETADDRINFO struct curltime happy_eyeballs_dns_time; /* when this timer started, or 0 */ #endif @@ -226,11 +222,11 @@ struct doh_probes; #else /* CURLRES_ASYNCH */ /* convert these functions if an asynch resolver is not used */ -#define Curl_async_get_impl(x,y) (*(y) = NULL, CURLE_OK) -#define Curl_async_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST -#define Curl_async_await(x,y) CURLE_COULDNT_RESOLVE_HOST -#define Curl_async_global_init() CURLE_OK -#define Curl_async_global_cleanup() Curl_nop_stmt +#define Curl_async_get_impl(x, y) (*(y) = NULL, CURLE_OK) +#define Curl_async_is_resolved(x, y) CURLE_COULDNT_RESOLVE_HOST +#define Curl_async_await(x, y) CURLE_COULDNT_RESOLVE_HOST +#define Curl_async_global_init() CURLE_OK +#define Curl_async_global_cleanup() Curl_nop_stmt #endif /* !CURLRES_ASYNCH */ @@ -270,9 +266,8 @@ void Curl_async_shutdown(struct Curl_easy *data); void Curl_async_destroy(struct Curl_easy *data); #else /* !USE_CURL_ASYNC */ #define Curl_async_shutdown(x) Curl_nop_stmt -#define Curl_async_destroy(x) Curl_nop_stmt +#define Curl_async_destroy(x) Curl_nop_stmt #endif /* USE_CURL_ASYNC */ - /********** end of generic resolver interface functions *****************/ #endif /* HEADER_CURL_ASYN_H */ diff --git a/lib/bufq.c b/lib/bufq.c index e429ccf8e375..6eeeeb35d432 100644 --- a/lib/bufq.c +++ b/lib/bufq.c @@ -25,10 +25,6 @@ #include "curl_setup.h" #include "bufq.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - static bool chunk_is_empty(const struct buf_chunk *chunk) { return chunk->r_offset >= chunk->w_offset; @@ -51,9 +47,9 @@ static void chunk_reset(struct buf_chunk *chunk) } static size_t chunk_append(struct buf_chunk *chunk, - const unsigned char *buf, size_t len) + const uint8_t *buf, size_t len) { - unsigned char *p = &chunk->x.data[chunk->w_offset]; + uint8_t *p = &chunk->x.data[chunk->w_offset]; size_t n = chunk->dlen - chunk->w_offset; DEBUGASSERT(chunk->dlen >= chunk->w_offset); if(n) { @@ -65,9 +61,9 @@ static size_t chunk_append(struct buf_chunk *chunk, } static size_t chunk_read(struct buf_chunk *chunk, - unsigned char *buf, size_t len) + uint8_t *buf, size_t len) { - unsigned char *p = &chunk->x.data[chunk->r_offset]; + uint8_t *p = &chunk->x.data[chunk->r_offset]; size_t n = chunk->w_offset - chunk->r_offset; DEBUGASSERT(chunk->w_offset >= chunk->r_offset); if(!n) { @@ -89,7 +85,7 @@ static CURLcode chunk_slurpn(struct buf_chunk *chunk, size_t max_len, Curl_bufq_reader *reader, void *reader_ctx, size_t *pnread) { - unsigned char *p = &chunk->x.data[chunk->w_offset]; + uint8_t *p = &chunk->x.data[chunk->w_offset]; size_t n = chunk->dlen - chunk->w_offset; /* free amount */ CURLcode result; @@ -108,7 +104,7 @@ static CURLcode chunk_slurpn(struct buf_chunk *chunk, size_t max_len, } static void chunk_peek(const struct buf_chunk *chunk, - const unsigned char **pbuf, size_t *plen) + const uint8_t **pbuf, size_t *plen) { DEBUGASSERT(chunk->w_offset >= chunk->r_offset); *pbuf = &chunk->x.data[chunk->r_offset]; @@ -116,7 +112,7 @@ static void chunk_peek(const struct buf_chunk *chunk, } static void chunk_peek_at(const struct buf_chunk *chunk, size_t offset, - const unsigned char **pbuf, size_t *plen) + const uint8_t **pbuf, size_t *plen) { offset += chunk->r_offset; DEBUGASSERT(chunk->w_offset >= offset); @@ -143,11 +139,10 @@ static void chunk_list_free(struct buf_chunk **anchor) while(*anchor) { chunk = *anchor; *anchor = chunk->next; - free(chunk); + curlx_free(chunk); } } - void Curl_bufcp_init(struct bufc_pool *pool, size_t chunk_size, size_t spare_max) { @@ -178,7 +173,7 @@ static CURLcode bufcp_take(struct bufc_pool *pool, return CURLE_OUT_OF_MEMORY; } - chunk = calloc(1, sizeof(*chunk) + pool->chunk_size); + chunk = curlx_calloc(1, sizeof(*chunk) + pool->chunk_size); if(!chunk) { *pchunk = NULL; return CURLE_OUT_OF_MEMORY; @@ -192,7 +187,7 @@ static void bufcp_put(struct bufc_pool *pool, struct buf_chunk *chunk) { if(pool->spare_count >= pool->spare_max) { - free(chunk); + curlx_free(chunk); } else { chunk_reset(chunk); @@ -311,7 +306,7 @@ static struct buf_chunk *get_spare(struct bufq *q) return NULL; } - chunk = calloc(1, sizeof(*chunk) + q->chunk_size); + chunk = curlx_calloc(1, sizeof(*chunk) + q->chunk_size); if(!chunk) return NULL; chunk->dlen = q->chunk_size; @@ -334,11 +329,11 @@ static void prune_head(struct bufq *q) --q->chunk_count; } else if((q->chunk_count > q->max_chunks) || - (q->opts & BUFQ_OPT_NO_SPARES)) { + (q->opts & BUFQ_OPT_NO_SPARES)) { /* SOFT_LIMIT allowed us more than max. free spares until * we are at max again. Or free them if we are configured * to not use spares. */ - free(chunk); + curlx_free(chunk); --q->chunk_count; } else { @@ -370,7 +365,7 @@ static struct buf_chunk *get_non_full_tail(struct bufq *q) } CURLcode Curl_bufq_write(struct bufq *q, - const unsigned char *buf, size_t len, + const uint8_t *buf, size_t len, size_t *pnwritten) { struct buf_chunk *tail; @@ -400,10 +395,10 @@ CURLcode Curl_bufq_cwrite(struct bufq *q, const char *buf, size_t len, size_t *pnwritten) { - return Curl_bufq_write(q, (const unsigned char *)buf, len, pnwritten); + return Curl_bufq_write(q, (const uint8_t *)buf, len, pnwritten); } -CURLcode Curl_bufq_read(struct bufq *q, unsigned char *buf, size_t len, +CURLcode Curl_bufq_read(struct bufq *q, uint8_t *buf, size_t len, size_t *pnread) { *pnread = 0; @@ -422,11 +417,11 @@ CURLcode Curl_bufq_read(struct bufq *q, unsigned char *buf, size_t len, CURLcode Curl_bufq_cread(struct bufq *q, char *buf, size_t len, size_t *pnread) { - return Curl_bufq_read(q, (unsigned char *)buf, len, pnread); + return Curl_bufq_read(q, (uint8_t *)buf, len, pnread); } bool Curl_bufq_peek(struct bufq *q, - const unsigned char **pbuf, size_t *plen) + const uint8_t **pbuf, size_t *plen) { if(q->head && chunk_is_empty(q->head)) { prune_head(q); @@ -441,7 +436,7 @@ bool Curl_bufq_peek(struct bufq *q, } bool Curl_bufq_peek_at(struct bufq *q, size_t offset, - const unsigned char **pbuf, size_t *plen) + const uint8_t **pbuf, size_t *plen) { struct buf_chunk *c = q->head; size_t clen; @@ -477,7 +472,7 @@ void Curl_bufq_skip(struct bufq *q, size_t amount) CURLcode Curl_bufq_pass(struct bufq *q, Curl_bufq_writer *writer, void *writer_ctx, size_t *pwritten) { - const unsigned char *buf; + const uint8_t *buf; size_t blen; CURLcode result = CURLE_OK; @@ -507,7 +502,7 @@ CURLcode Curl_bufq_pass(struct bufq *q, Curl_bufq_writer *writer, } CURLcode Curl_bufq_write_pass(struct bufq *q, - const unsigned char *buf, size_t len, + const uint8_t *buf, size_t len, Curl_bufq_writer *writer, void *writer_ctx, size_t *pwritten) { diff --git a/lib/bufq.h b/lib/bufq.h index ad8e6435fae1..bcd7df2ab9dd 100644 --- a/lib/bufq.h +++ b/lib/bufq.h @@ -25,8 +25,6 @@ ***************************************************************************/ #include "curl_setup.h" -#include - /** * A chunk of bytes for reading and writing. * The size is fixed a creation with read and write offset @@ -38,7 +36,7 @@ struct buf_chunk { size_t r_offset; /* first unread bytes */ size_t w_offset; /* one after last written byte */ union { - unsigned char data[1]; /* the buffer for `dlen` bytes */ + uint8_t data[1]; /* the buffer for `dlen` bytes */ void *dummy; /* alignment */ } x; }; @@ -166,7 +164,7 @@ bool Curl_bufq_is_full(const struct bufq *q); * CURLE_AGAIN is returned if the buffer queue is full. */ CURLcode Curl_bufq_write(struct bufq *q, - const unsigned char *buf, size_t len, + const uint8_t *buf, size_t len, size_t *pnwritten); CURLcode Curl_bufq_cwrite(struct bufq *q, @@ -177,7 +175,7 @@ CURLcode Curl_bufq_cwrite(struct bufq *q, * Read buf from the start of the buffer queue. The buf is copied * and the amount of copied bytes is returned. */ -CURLcode Curl_bufq_read(struct bufq *q, unsigned char *buf, size_t len, +CURLcode Curl_bufq_read(struct bufq *q, uint8_t *buf, size_t len, size_t *pnread); CURLcode Curl_bufq_cread(struct bufq *q, char *buf, size_t len, @@ -193,10 +191,10 @@ CURLcode Curl_bufq_cread(struct bufq *q, char *buf, size_t len, * is modified, see `Curl_bufq_skip()`` */ bool Curl_bufq_peek(struct bufq *q, - const unsigned char **pbuf, size_t *plen); + const uint8_t **pbuf, size_t *plen); bool Curl_bufq_peek_at(struct bufq *q, size_t offset, - const unsigned char **pbuf, size_t *plen); + const uint8_t **pbuf, size_t *plen); /** * Tell the buffer queue to discard `amount` buf bytes at the head @@ -206,7 +204,7 @@ bool Curl_bufq_peek_at(struct bufq *q, size_t offset, void Curl_bufq_skip(struct bufq *q, size_t amount); typedef CURLcode Curl_bufq_writer(void *writer_ctx, - const unsigned char *buf, size_t len, + const uint8_t *buf, size_t len, size_t *pwritten); /** * Passes the chunks in the buffer queue to the writer and returns @@ -221,7 +219,7 @@ CURLcode Curl_bufq_pass(struct bufq *q, Curl_bufq_writer *writer, void *writer_ctx, size_t *pwritten); typedef CURLcode Curl_bufq_reader(void *reader_ctx, - unsigned char *buf, size_t len, + uint8_t *buf, size_t len, size_t *pnread); /** @@ -253,7 +251,7 @@ CURLcode Curl_bufq_sipn(struct bufq *q, size_t max_len, * amount buffered, chunk size, etc. */ CURLcode Curl_bufq_write_pass(struct bufq *q, - const unsigned char *buf, size_t len, + const uint8_t *buf, size_t len, Curl_bufq_writer *writer, void *writer_ctx, size_t *pwritten); diff --git a/lib/bufref.c b/lib/bufref.c index ac0612071d6c..e5b5a4d985cd 100644 --- a/lib/bufref.c +++ b/lib/bufref.c @@ -27,9 +27,6 @@ #include "bufref.h" #include "strdup.h" -#include "curl_memory.h" -#include "memdebug.h" - #ifdef DEBUGBUILD #define SIGNATURE 0x5c48e9b2 /* Random pattern. */ #endif @@ -79,7 +76,7 @@ void Curl_bufref_set(struct bufref *br, const void *ptr, size_t len, DEBUGASSERT(len <= CURL_MAX_INPUT_LENGTH); Curl_bufref_free(br); - br->ptr = (const unsigned char *) ptr; + br->ptr = (const unsigned char *)ptr; br->len = len; br->dtor = dtor; } @@ -87,7 +84,7 @@ void Curl_bufref_set(struct bufref *br, const void *ptr, size_t len, /* * Get a pointer to the referenced buffer. */ -const unsigned char *Curl_bufref_ptr(const struct bufref *br) +const unsigned char *Curl_bufref_uptr(const struct bufref *br) { DEBUGASSERT(br); DEBUGASSERT(br->signature == SIGNATURE); @@ -96,6 +93,18 @@ const unsigned char *Curl_bufref_ptr(const struct bufref *br) return br->ptr; } +/* + * Get a pointer to the referenced string. + */ +const char *Curl_bufref_ptr(const struct bufref *br) +{ + DEBUGASSERT(br); + DEBUGASSERT(br->signature == SIGNATURE); + DEBUGASSERT(br->ptr || !br->len); + + return (const char *)br->ptr; +} + /* * Get the length of the referenced buffer data. */ @@ -108,7 +117,7 @@ size_t Curl_bufref_len(const struct bufref *br) return br->len; } -CURLcode Curl_bufref_memdup(struct bufref *br, const void *ptr, size_t len) +CURLcode Curl_bufref_memdup0(struct bufref *br, const void *ptr, size_t len) { unsigned char *cpy = NULL; diff --git a/lib/bufref.h b/lib/bufref.h index dd424f18f556..5d331adbdf0f 100644 --- a/lib/bufref.h +++ b/lib/bufref.h @@ -36,13 +36,16 @@ struct bufref { #endif }; - void Curl_bufref_init(struct bufref *br); void Curl_bufref_set(struct bufref *br, const void *ptr, size_t len, void (*dtor)(void *)); -const unsigned char *Curl_bufref_ptr(const struct bufref *br); +const char *Curl_bufref_ptr(const struct bufref *br); +const unsigned char *Curl_bufref_uptr(const struct bufref *br); size_t Curl_bufref_len(const struct bufref *br); -CURLcode Curl_bufref_memdup(struct bufref *br, const void *ptr, size_t len); +CURLcode Curl_bufref_memdup0(struct bufref *br, const void *ptr, size_t len); void Curl_bufref_free(struct bufref *br); +/* return a strdup() version of the buffer */ +#define Curl_bufref_dup(x) curlx_strdup(Curl_bufref_ptr(x)) + #endif diff --git a/lib/cf-h1-proxy.c b/lib/cf-h1-proxy.c index e65aa74ddb87..83b8239d45b7 100644 --- a/lib/cf-h1-proxy.c +++ b/lib/cf-h1-proxy.c @@ -26,7 +26,6 @@ #if !defined(CURL_DISABLE_PROXY) && !defined(CURL_DISABLE_HTTP) -#include #include "urldata.h" #include "curlx/dynbuf.h" #include "sendf.h" @@ -41,23 +40,17 @@ #include "connect.h" #include "curl_trc.h" #include "strcase.h" -#include "vtls/vtls.h" #include "transfer.h" -#include "multiif.h" #include "curlx/strparse.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - typedef enum { - H1_TUNNEL_INIT, /* init/default/no tunnel state */ - H1_TUNNEL_CONNECT, /* CONNECT request is being send */ - H1_TUNNEL_RECEIVE, /* CONNECT answer is being received */ - H1_TUNNEL_RESPONSE, /* CONNECT response received completely */ - H1_TUNNEL_ESTABLISHED, - H1_TUNNEL_FAILED + H1_TUNNEL_INIT, /* init/default/no tunnel state */ + H1_TUNNEL_CONNECT, /* CONNECT request is being send */ + H1_TUNNEL_RECEIVE, /* CONNECT answer is being received */ + H1_TUNNEL_RESPONSE, /* CONNECT response received completely */ + H1_TUNNEL_ESTABLISHED, + H1_TUNNEL_FAILED } h1_tunnel_state; /* struct for HTTP CONNECT tunneling */ @@ -78,7 +71,6 @@ struct h1_tunnel_state { BIT(close_connection); }; - static bool tunnel_is_established(struct h1_tunnel_state *ts) { return ts && (ts->tunnel_state == H1_TUNNEL_ESTABLISHED); @@ -116,7 +108,7 @@ static CURLcode tunnel_init(struct Curl_cfilter *cf, return CURLE_UNSUPPORTED_PROTOCOL; } - ts = calloc(1, sizeof(*ts)); + ts = curlx_calloc(1, sizeof(*ts)); if(!ts) return CURLE_OUT_OF_MEMORY; @@ -126,8 +118,7 @@ static CURLcode tunnel_init(struct Curl_cfilter *cf, curlx_dyn_init(&ts->request_data, DYN_HTTP_REQUEST); Curl_httpchunk_init(data, &ts->ch, TRUE); - *pts = ts; - connkeep(cf->conn, "HTTP proxy CONNECT"); + *pts = ts; return tunnel_reinit(cf, data, ts); } @@ -175,7 +166,7 @@ static void h1_tunnel_go_state(struct Curl_cfilter *cf, curlx_dyn_reset(&ts->rcvbuf); curlx_dyn_reset(&ts->request_data); /* restore the protocol pointer */ - data->info.httpcode = 0; /* clear it as it might've been used for the + data->info.httpcode = 0; /* clear it as it might have been used for the proxy */ /* If a proxy-authorization header was used for the proxy, then we should make sure that it is not accidentally used for the document request @@ -195,7 +186,7 @@ static void tunnel_free(struct Curl_cfilter *cf, curlx_dyn_free(&ts->rcvbuf); curlx_dyn_free(&ts->request_data); Curl_httpchunk_free(data, &ts->ch); - free(ts); + curlx_free(ts); cf->ctx = NULL; } } @@ -214,9 +205,9 @@ static CURLcode start_CONNECT(struct Curl_cfilter *cf, int http_minor; CURLcode result; - /* This only happens if we have looped here due to authentication - reasons, and we do not really use the newly cloned URL here - then. Just free() it. */ + /* This only happens if we have looped here due to authentication + reasons, and we do not really use the newly cloned URL here + then. Just free it. */ Curl_safefree(data->req.newurl); result = Curl_http_proxy_create_CONNECT(&req, cf, data, 1); @@ -247,7 +238,7 @@ static CURLcode send_CONNECT(struct Curl_cfilter *cf, struct h1_tunnel_state *ts, bool *done) { - char *buf = curlx_dyn_ptr(&ts->request_data); + uint8_t *buf = curlx_dyn_uptr(&ts->request_data); size_t request_len = curlx_dyn_len(&ts->request_data); size_t blen = request_len; CURLcode result = CURLE_OK; @@ -268,7 +259,7 @@ static CURLcode send_CONNECT(struct Curl_cfilter *cf, DEBUGASSERT(blen >= nwritten); ts->nsent += nwritten; - Curl_debug(data, CURLINFO_HEADER_OUT, buf, (size_t)nwritten); + Curl_debug(data, CURLINFO_HEADER_OUT, (char *)buf, nwritten); out: if(result) @@ -286,10 +277,8 @@ static CURLcode on_resp_header(struct Curl_cfilter *cf, struct SingleRequest *k = &data->req; (void)cf; - if((checkprefix("WWW-Authenticate:", header) && - (401 == k->httpcode)) || - (checkprefix("Proxy-authenticate:", header) && - (407 == k->httpcode))) { + if((checkprefix("WWW-Authenticate:", header) && (401 == k->httpcode)) || + (checkprefix("Proxy-authenticate:", header) && (407 == k->httpcode))) { bool proxy = (k->httpcode == 407); char *auth = Curl_copy_header_value(header); @@ -299,13 +288,13 @@ static CURLcode on_resp_header(struct Curl_cfilter *cf, CURL_TRC_CF(data, cf, "CONNECT: fwd auth header '%s'", header); result = Curl_http_input_auth(data, proxy, auth); - free(auth); + curlx_free(auth); if(result) return result; } else if(checkprefix("Content-Length:", header)) { - if(k->httpcode/100 == 2) { + if(k->httpcode / 100 == 2) { /* A client MUST ignore any Content-Length or Transfer-Encoding header fields received in a successful response to CONNECT. "Successful" described as: 2xx (Successful). RFC 7231 4.3.6 */ @@ -324,7 +313,7 @@ static CURLcode on_resp_header(struct Curl_cfilter *cf, STRCONST("Connection:"), STRCONST("close"))) ts->close_connection = TRUE; else if(checkprefix("Transfer-Encoding:", header)) { - if(k->httpcode/100 == 2) { + if(k->httpcode / 100 == 2) { /* A client MUST ignore any Content-Length or Transfer-Encoding header fields received in a successful response to CONNECT. "Successful" described as: 2xx (Successful). RFC 7231 4.3.6 */ @@ -350,7 +339,7 @@ static CURLcode on_resp_header(struct Curl_cfilter *cf, ISDIGIT(header[9]) && ISDIGIT(header[10]) && ISDIGIT(header[11]) && !ISDIGIT(header[12])) { /* store the HTTP code from the proxy */ - data->info.httpproxycode = k->httpcode = (header[9] - '0') * 100 + + data->info.httpproxycode = k->httpcode = (header[9] - '0') * 100 + (header[10] - '0') * 10 + (header[11] - '0'); } return result; @@ -384,8 +373,8 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf, /* socket buffer drained, return */ return CURLE_OK; - if(Curl_pgrsUpdate(data)) - return CURLE_ABORTED_BY_CALLBACK; + if(!result) + result = Curl_pgrsUpdate(data); if(result) { ts->keepon = KEEPON_DONE; @@ -498,8 +487,8 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf, ts->keepon = KEEPON_DONE; } - DEBUGASSERT(ts->keepon == KEEPON_IGNORE - || ts->keepon == KEEPON_DONE); + DEBUGASSERT(ts->keepon == KEEPON_IGNORE || + ts->keepon == KEEPON_DONE); continue; } @@ -513,7 +502,7 @@ static CURLcode recv_CONNECT_resp(struct Curl_cfilter *cf, if(error) result = CURLE_RECV_ERROR; *done = (ts->keepon == KEEPON_DONE); - if(!result && *done && data->info.httpproxycode/100 != 2) { + if(!result && *done && data->info.httpproxycode / 100 != 2) { /* Deal with the possibly already received authenticate headers. 'newurl' is set to a new URL if we must loop. */ result = Curl_http_auth_act(data); @@ -535,10 +524,8 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf, return CURLE_RECV_ERROR; /* Need a cfilter close and new bootstrap */ do { - timediff_t check; - check = Curl_timeleft(data, NULL, TRUE); - if(check <= 0) { + if(Curl_timeleft_ms(data, TRUE) < 0) { failf(data, "Proxy CONNECT aborted due to timeout"); result = CURLE_OPERATION_TIMEDOUT; goto out; @@ -567,10 +554,8 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf, /* read what is there */ CURL_TRC_CF(data, cf, "CONNECT receive"); result = recv_CONNECT_resp(cf, data, ts, &done); - if(Curl_pgrsUpdate(data)) { - result = CURLE_ABORTED_BY_CALLBACK; - goto out; - } + if(!result) + result = Curl_pgrsUpdate(data); /* error or not complete yet. return for more multi-multi */ if(result || !done) goto out; @@ -595,7 +580,6 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf, CURL_TRC_CF(data, cf, "CONNECT need to close+open"); infof(data, "Connect me again please"); Curl_conn_cf_close(cf, data); - connkeep(conn, "HTTP proxy CONNECT"); result = Curl_conn_cf_connect(cf->next, data, &done); goto out; } @@ -613,11 +597,9 @@ static CURLcode H1_CONNECT(struct Curl_cfilter *cf, } while(data->req.newurl); DEBUGASSERT(ts->tunnel_state == H1_TUNNEL_RESPONSE); - if(data->info.httpproxycode/100 != 2) { + if(data->info.httpproxycode / 100 != 2) { /* a non-2xx response and we have no next URL to try. */ Curl_safefree(data->req.newurl); - /* failure, close this connection to avoid reuse */ - streamclose(conn, "proxy CONNECT failure"); h1_tunnel_go_state(cf, ts, H1_TUNNEL_FAILED, data); failf(data, "CONNECT tunnel failed, response %d", data->req.httpcode); return CURLE_RECV_ERROR; @@ -673,8 +655,7 @@ static CURLcode cf_h1_proxy_connect(struct Curl_cfilter *cf, /* The real request will follow the CONNECT, reset request partially */ Curl_req_soft_reset(&data->req, data); Curl_client_reset(data); - Curl_pgrsSetUploadCounter(data, 0); - Curl_pgrsSetDownloadCounter(data, 0); + Curl_pgrsReset(data); tunnel_free(cf, data); } @@ -729,10 +710,9 @@ static void cf_h1_proxy_close(struct Curl_cfilter *cf, } } - struct Curl_cftype Curl_cft_h1_proxy = { "H1-PROXY", - CF_TYPE_IP_CONNECT|CF_TYPE_PROXY, + CF_TYPE_IP_CONNECT | CF_TYPE_PROXY, 0, cf_h1_proxy_destroy, cf_h1_proxy_connect, diff --git a/lib/cf-h1-proxy.h b/lib/cf-h1-proxy.h index ac5bed0b2bc7..ded55db9df31 100644 --- a/lib/cf-h1-proxy.h +++ b/lib/cf-h1-proxy.h @@ -33,7 +33,6 @@ CURLcode Curl_cf_h1_proxy_insert_after(struct Curl_cfilter *cf, extern struct Curl_cftype Curl_cft_h1_proxy; - #endif /* !CURL_DISABLE_PROXY && !CURL_DISABLE_HTTP */ #endif /* HEADER_CURL_H1_PROXY_H */ diff --git a/lib/cf-h2-proxy.c b/lib/cf-h2-proxy.c index 8baa227aac22..cc9a1672d0bc 100644 --- a/lib/cf-h2-proxy.c +++ b/lib/cf-h2-proxy.c @@ -28,6 +28,7 @@ defined(USE_NGHTTP2) #include + #include "urldata.h" #include "url.h" #include "cfilters.h" @@ -44,16 +45,12 @@ #include "select.h" #include "cf-h2-proxy.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - -#define PROXY_H2_CHUNK_SIZE (16*1024) +#define PROXY_H2_CHUNK_SIZE (16 * 1024) #define PROXY_HTTP2_HUGE_WINDOW_SIZE (100 * 1024 * 1024) #define H2_TUNNEL_WINDOW_SIZE (10 * 1024 * 1024) -#define PROXY_H2_NW_RECV_CHUNKS (H2_TUNNEL_WINDOW_SIZE / PROXY_H2_CHUNK_SIZE) +#define PROXY_H2_NW_RECV_CHUNKS (H2_TUNNEL_WINDOW_SIZE / PROXY_H2_CHUNK_SIZE) #define PROXY_H2_NW_SEND_CHUNKS 1 #define H2_TUNNEL_RECV_CHUNKS (H2_TUNNEL_WINDOW_SIZE / PROXY_H2_CHUNK_SIZE) @@ -61,11 +58,11 @@ typedef enum { - H2_TUNNEL_INIT, /* init/default/no tunnel state */ - H2_TUNNEL_CONNECT, /* CONNECT request is being send */ - H2_TUNNEL_RESPONSE, /* CONNECT response received completely */ - H2_TUNNEL_ESTABLISHED, - H2_TUNNEL_FAILED + H2_TUNNEL_INIT, /* init/default/no tunnel state */ + H2_TUNNEL_CONNECT, /* CONNECT request is being send */ + H2_TUNNEL_RESPONSE, /* CONNECT response received completely */ + H2_TUNNEL_ESTABLISHED, + H2_TUNNEL_FAILED } h2_tunnel_state; struct tunnel_stream { @@ -87,7 +84,6 @@ static CURLcode tunnel_stream_init(struct Curl_cfilter *cf, const char *hostname; int port; bool ipv6_ip; - CURLcode result; ts->state = H2_TUNNEL_INIT; ts->stream_id = -1; @@ -95,13 +91,11 @@ static CURLcode tunnel_stream_init(struct Curl_cfilter *cf, BUFQ_OPT_SOFT_LIMIT); Curl_bufq_init(&ts->sendbuf, PROXY_H2_CHUNK_SIZE, H2_TUNNEL_SEND_CHUNKS); - result = Curl_http_proxy_get_destination(cf, &hostname, &port, &ipv6_ip); - if(result) - return result; + Curl_http_proxy_get_destination(cf, &hostname, &port, &ipv6_ip); - ts->authority = /* host:port with IPv6 support */ - curl_maprintf("%s%s%s:%d", ipv6_ip ? "[":"", hostname, - ipv6_ip ? "]" : "", port); + /* host:port with IPv6 support */ + ts->authority = curl_maprintf("%s%s%s:%d", ipv6_ip ? "[" : "", hostname, + ipv6_ip ? "]" : "", port); if(!ts->authority) return CURLE_OUT_OF_MEMORY; @@ -190,8 +184,7 @@ struct cf_h2_proxy_ctx { /* How to access `call_data` from a cf_h2 filter */ #undef CF_CTX_CALL_DATA -#define CF_CTX_CALL_DATA(cf) \ - ((struct cf_h2_proxy_ctx *)(cf)->ctx)->call_data +#define CF_CTX_CALL_DATA(cf) ((struct cf_h2_proxy_ctx *)(cf)->ctx)->call_data static void cf_h2_proxy_ctx_clear(struct cf_h2_proxy_ctx *ctx) { @@ -211,7 +204,7 @@ static void cf_h2_proxy_ctx_free(struct cf_h2_proxy_ctx *ctx) { if(ctx) { cf_h2_proxy_ctx_clear(ctx); - free(ctx); + curlx_free(ctx); } } @@ -227,7 +220,7 @@ static void drain_tunnel(struct Curl_cfilter *cf, } static CURLcode proxy_h2_nw_out_writer(void *writer_ctx, - const unsigned char *buf, size_t buflen, + const uint8_t *buf, size_t buflen, size_t *pnwritten) { struct Curl_cfilter *cf = writer_ctx; @@ -235,7 +228,7 @@ static CURLcode proxy_h2_nw_out_writer(void *writer_ctx, if(cf) { struct Curl_easy *data = CF_DATA_CURRENT(cf); CURLcode result; - result = Curl_conn_cf_send(cf->next, data, (const char *)buf, buflen, + result = Curl_conn_cf_send(cf->next, data, buf, buflen, FALSE, pnwritten); CURL_TRC_CF(data, cf, "[0] nw_out_writer(len=%zu) -> %d, %zu", buflen, result, *pnwritten); @@ -249,8 +242,8 @@ static int proxy_h2_client_new(struct Curl_cfilter *cf, { struct cf_h2_proxy_ctx *ctx = cf->ctx; nghttp2_option *o; - nghttp2_mem mem = {NULL, Curl_nghttp2_malloc, Curl_nghttp2_free, - Curl_nghttp2_calloc, Curl_nghttp2_realloc}; + nghttp2_mem mem = { NULL, Curl_nghttp2_malloc, Curl_nghttp2_free, + Curl_nghttp2_calloc, Curl_nghttp2_realloc }; int rc = nghttp2_option_new(&o); if(rc) @@ -314,7 +307,7 @@ static CURLcode cf_h2_proxy_ctx_init(struct Curl_cfilter *cf, rc = nghttp2_session_callbacks_new(&cbs); if(rc) { - failf(data, "Couldn't initialize nghttp2 callbacks"); + failf(data, "Could not initialize nghttp2 callbacks"); goto out; } @@ -334,7 +327,7 @@ static CURLcode cf_h2_proxy_ctx_init(struct Curl_cfilter *cf, /* The nghttp2 session is not yet setup, do it */ rc = proxy_h2_client_new(cf, cbs); if(rc) { - failf(data, "Couldn't initialize nghttp2"); + failf(data, "Could not initialize nghttp2"); goto out; } @@ -365,7 +358,6 @@ static CURLcode cf_h2_proxy_ctx_init(struct Curl_cfilter *cf, goto out; } - /* all set, traffic will be send on connect */ result = CURLE_OK; @@ -412,32 +404,30 @@ static CURLcode proxy_h2_nw_out_flush(struct Curl_cfilter *cf, * This function returns 0 if it succeeds, or -1 and error code will * be assigned to *err. */ -static int proxy_h2_process_pending_input(struct Curl_cfilter *cf, - struct Curl_easy *data, - CURLcode *err) +static CURLcode proxy_h2_process_pending_input(struct Curl_cfilter *cf, + struct Curl_easy *data) { struct cf_h2_proxy_ctx *ctx = cf->ctx; const unsigned char *buf; - size_t blen; + size_t blen, nread; ssize_t rv; while(Curl_bufq_peek(&ctx->inbufq, &buf, &blen)) { rv = nghttp2_session_mem_recv(ctx->h2, (const uint8_t *)buf, blen); CURL_TRC_CF(data, cf, "[0] %zu bytes to nghttp2 -> %zd", blen, rv); - if(rv < 0) { + if(!curlx_sztouz(rv, &nread)) { failf(data, "process_pending_input: nghttp2_session_mem_recv() returned " "%zd:%s", rv, nghttp2_strerror((int)rv)); - *err = CURLE_RECV_ERROR; - return -1; + return CURLE_RECV_ERROR; } - else if(!rv) { + else if(!nread) { /* nghttp2 does not want to process more, but has no error. This * probably cannot happen, but be safe. */ break; } - Curl_bufq_skip(&ctx->inbufq, (size_t)rv); + Curl_bufq_skip(&ctx->inbufq, nread); if(Curl_bufq_is_empty(&ctx->inbufq)) { CURL_TRC_CF(data, cf, "[0] all data in connection buffer processed"); break; @@ -447,8 +437,7 @@ static int proxy_h2_process_pending_input(struct Curl_cfilter *cf, "in connection buffer", Curl_bufq_len(&ctx->inbufq)); } } - - return 0; + return CURLE_OK; } static CURLcode proxy_h2_progress_ingress(struct Curl_cfilter *cf, @@ -462,14 +451,15 @@ static CURLcode proxy_h2_progress_ingress(struct Curl_cfilter *cf, if(!Curl_bufq_is_empty(&ctx->inbufq)) { CURL_TRC_CF(data, cf, "[0] process %zu bytes in connection buffer", Curl_bufq_len(&ctx->inbufq)); - if(proxy_h2_process_pending_input(cf, data, &result) < 0) + result = proxy_h2_process_pending_input(cf, data); + if(result) return result; } /* Receive data from the "lower" filters, e.g. network until * it is time to stop or we have enough data for this stream */ - while(!ctx->conn_closed && /* not closed the connection */ - !ctx->tunnel.closed && /* nor the tunnel */ + while(!ctx->conn_closed && /* not closed the connection */ + !ctx->tunnel.closed && /* nor the tunnel */ Curl_bufq_is_empty(&ctx->inbufq) && /* and we consumed our input */ !Curl_bufq_is_full(&ctx->tunnel.recvbuf)) { @@ -488,14 +478,11 @@ static CURLcode proxy_h2_progress_ingress(struct Curl_cfilter *cf, break; } - if(proxy_h2_process_pending_input(cf, data, &result)) + result = proxy_h2_process_pending_input(cf, data); + if(result) return result; } - if(ctx->conn_closed && Curl_bufq_is_empty(&ctx->inbufq)) { - connclose(cf->conn, "GOAWAY received"); - } - return CURLE_OK; } @@ -554,70 +541,70 @@ static int proxy_h2_fr_print(const nghttp2_frame *frame, char *buffer, size_t blen) { switch(frame->hd.type) { - case NGHTTP2_DATA: { - return curl_msnprintf(buffer, blen, - "FRAME[DATA, len=%d, eos=%d, padlen=%d]", - (int)frame->hd.length, - !!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM), - (int)frame->data.padlen); - } - case NGHTTP2_HEADERS: { - return curl_msnprintf(buffer, blen, - "FRAME[HEADERS, len=%d, hend=%d, eos=%d]", - (int)frame->hd.length, - !!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS), - !!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM)); - } - case NGHTTP2_PRIORITY: { - return curl_msnprintf(buffer, blen, - "FRAME[PRIORITY, len=%d, flags=%d]", - (int)frame->hd.length, frame->hd.flags); - } - case NGHTTP2_RST_STREAM: { - return curl_msnprintf(buffer, blen, - "FRAME[RST_STREAM, len=%d, flags=%d, error=%u]", - (int)frame->hd.length, frame->hd.flags, - frame->rst_stream.error_code); - } - case NGHTTP2_SETTINGS: { - if(frame->hd.flags & NGHTTP2_FLAG_ACK) { - return curl_msnprintf(buffer, blen, "FRAME[SETTINGS, ack=1]"); - } - return curl_msnprintf(buffer, blen, - "FRAME[SETTINGS, len=%d]", (int)frame->hd.length); + case NGHTTP2_DATA: { + return curl_msnprintf(buffer, blen, + "FRAME[DATA, len=%d, eos=%d, padlen=%d]", + (int)frame->hd.length, + !!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM), + (int)frame->data.padlen); + } + case NGHTTP2_HEADERS: { + return curl_msnprintf(buffer, blen, + "FRAME[HEADERS, len=%d, hend=%d, eos=%d]", + (int)frame->hd.length, + !!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS), + !!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM)); + } + case NGHTTP2_PRIORITY: { + return curl_msnprintf(buffer, blen, + "FRAME[PRIORITY, len=%d, flags=%d]", + (int)frame->hd.length, frame->hd.flags); + } + case NGHTTP2_RST_STREAM: { + return curl_msnprintf(buffer, blen, + "FRAME[RST_STREAM, len=%d, flags=%d, error=%u]", + (int)frame->hd.length, frame->hd.flags, + frame->rst_stream.error_code); + } + case NGHTTP2_SETTINGS: { + if(frame->hd.flags & NGHTTP2_FLAG_ACK) { + return curl_msnprintf(buffer, blen, "FRAME[SETTINGS, ack=1]"); } - case NGHTTP2_PUSH_PROMISE: - return curl_msnprintf(buffer, blen, - "FRAME[PUSH_PROMISE, len=%d, hend=%d]", - (int)frame->hd.length, - !!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS)); - case NGHTTP2_PING: - return curl_msnprintf(buffer, blen, - "FRAME[PING, len=%d, ack=%d]", - (int)frame->hd.length, - frame->hd.flags & NGHTTP2_FLAG_ACK); - case NGHTTP2_GOAWAY: { - char scratch[128]; - size_t s_len = CURL_ARRAYSIZE(scratch); - size_t len = (frame->goaway.opaque_data_len < s_len) ? - frame->goaway.opaque_data_len : s_len-1; - if(len) - memcpy(scratch, frame->goaway.opaque_data, len); - scratch[len] = '\0'; - return curl_msnprintf(buffer, blen, - "FRAME[GOAWAY, error=%d, reason='%s', " - "last_stream=%d]", frame->goaway.error_code, - scratch, frame->goaway.last_stream_id); - } - case NGHTTP2_WINDOW_UPDATE: { - return curl_msnprintf(buffer, blen, - "FRAME[WINDOW_UPDATE, incr=%d]", - frame->window_update.window_size_increment); - } - default: - return curl_msnprintf(buffer, blen, "FRAME[%d, len=%d, flags=%d]", - frame->hd.type, (int)frame->hd.length, - frame->hd.flags); + return curl_msnprintf(buffer, blen, + "FRAME[SETTINGS, len=%d]", (int)frame->hd.length); + } + case NGHTTP2_PUSH_PROMISE: + return curl_msnprintf(buffer, blen, + "FRAME[PUSH_PROMISE, len=%d, hend=%d]", + (int)frame->hd.length, + !!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS)); + case NGHTTP2_PING: + return curl_msnprintf(buffer, blen, + "FRAME[PING, len=%d, ack=%d]", + (int)frame->hd.length, + frame->hd.flags & NGHTTP2_FLAG_ACK); + case NGHTTP2_GOAWAY: { + char scratch[128]; + size_t s_len = CURL_ARRAYSIZE(scratch); + size_t len = (frame->goaway.opaque_data_len < s_len) ? + frame->goaway.opaque_data_len : s_len-1; + if(len) + memcpy(scratch, frame->goaway.opaque_data, len); + scratch[len] = '\0'; + return curl_msnprintf(buffer, blen, + "FRAME[GOAWAY, error=%d, reason='%s', " + "last_stream=%d]", frame->goaway.error_code, + scratch, frame->goaway.last_stream_id); + } + case NGHTTP2_WINDOW_UPDATE: { + return curl_msnprintf(buffer, blen, + "FRAME[WINDOW_UPDATE, incr=%d]", + frame->window_update.window_size_increment); + } + default: + return curl_msnprintf(buffer, blen, "FRAME[%d, len=%d, flags=%d]", + frame->hd.type, (int)frame->hd.length, + frame->hd.flags); } } @@ -633,7 +620,7 @@ static int proxy_h2_on_frame_send(nghttp2_session *session, if(data && Curl_trc_cf_is_verbose(cf, data)) { char buffer[256]; int len; - len = proxy_h2_fr_print(frame, buffer, sizeof(buffer)-1); + len = proxy_h2_fr_print(frame, buffer, sizeof(buffer) - 1); buffer[len] = 0; CURL_TRC_CF(data, cf, "[%d] -> %s", frame->hd.stream_id, buffer); } @@ -656,9 +643,9 @@ static int proxy_h2_on_frame_recv(nghttp2_session *session, if(Curl_trc_cf_is_verbose(cf, data)) { char buffer[256]; int len; - len = proxy_h2_fr_print(frame, buffer, sizeof(buffer)-1); + len = proxy_h2_fr_print(frame, buffer, sizeof(buffer) - 1); buffer[len] = 0; - CURL_TRC_CF(data, cf, "[%d] <- %s",frame->hd.stream_id, buffer); + CURL_TRC_CF(data, cf, "[%d] <- %s", frame->hd.stream_id, buffer); } #endif /* !CURL_DISABLE_VERBOSE_STRINGS */ @@ -851,7 +838,7 @@ static int tunnel_recv_callback(nghttp2_session *session, uint8_t flags, #endif } /* tunnel.recbuf has soft limit, any success MUST add all data */ - DEBUGASSERT((size_t)nwritten == len); + DEBUGASSERT(nwritten == len); return 0; } @@ -927,7 +914,7 @@ static CURLcode proxy_h2_submit(int32_t *pstream_id, result = CURLE_OK; out: - free(nva); + curlx_free(nva); Curl_dynhds_free(&h2_headers); *pstream_id = stream_id; return result; @@ -974,7 +961,7 @@ static CURLcode inspect_response(struct Curl_cfilter *cf, (void)cf; DEBUGASSERT(ts->resp); - if(ts->resp->status/100 == 2) { + if(ts->resp->status / 100 == 2) { infof(data, "CONNECT tunnel established, response %d", ts->resp->status); h2_tunnel_go_state(cf, ts, H2_TUNNEL_ESTABLISHED, data); return CURLE_OK; @@ -1077,7 +1064,6 @@ static CURLcode cf_h2_proxy_connect(struct Curl_cfilter *cf, struct cf_h2_proxy_ctx *ctx = cf->ctx; CURLcode result = CURLE_OK; struct cf_call_data save; - timediff_t check; struct tunnel_stream *ts = &ctx->tunnel; if(cf->connected) { @@ -1102,8 +1088,7 @@ static CURLcode cf_h2_proxy_connect(struct Curl_cfilter *cf, } DEBUGASSERT(ts->authority); - check = Curl_timeleft(data, NULL, TRUE); - if(check <= 0) { + if(Curl_timeleft_ms(data, TRUE) < 0) { failf(data, "Proxy CONNECT aborted due to timeout"); result = CURLE_OPERATION_TIMEDOUT; goto out; @@ -1234,7 +1219,7 @@ static CURLcode cf_h2_proxy_adjust_pollset(struct Curl_cfilter *cf, 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); + 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)) || @@ -1271,7 +1256,7 @@ static CURLcode h2_handle_tunnel_close(struct Curl_cfilter *cf, if(ctx->tunnel.error == NGHTTP2_REFUSED_STREAM) { CURL_TRC_CF(data, cf, "[%d] REFUSED_STREAM, try again on a new " "connection", ctx->tunnel.stream_id); - connclose(cf->conn, "REFUSED_STREAM"); /* do not use this anymore */ + failf(data, "proxy server refused HTTP/2 stream"); return CURLE_RECV_ERROR; /* trigger Curl_retry_request() later */ } else if(ctx->tunnel.error != NGHTTP2_NO_ERROR) { @@ -1366,7 +1351,7 @@ static CURLcode cf_h2_proxy_recv(struct Curl_cfilter *cf, static CURLcode cf_h2_proxy_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, bool eos, + const uint8_t *buf, size_t len, bool eos, size_t *pnwritten) { struct cf_h2_proxy_ctx *ctx = cf->ctx; @@ -1428,7 +1413,7 @@ static CURLcode cf_h2_proxy_send(struct Curl_cfilter *cf, "h2 windows %d-%d (stream-conn), buffers %zu-%zu (stream-conn)", ctx->tunnel.stream_id, len, result, *pnwritten, nghttp2_session_get_stream_remote_window_size( - ctx->h2, ctx->tunnel.stream_id), + ctx->h2, ctx->tunnel.stream_id), nghttp2_session_get_remote_window_size(ctx->h2), Curl_bufq_len(&ctx->tunnel.sendbuf), Curl_bufq_len(&ctx->outbufq)); @@ -1489,7 +1474,7 @@ static bool proxy_h2_connisalive(struct Curl_cfilter *cf, *input_pending = FALSE; result = Curl_cf_recv_bufq(cf->next, data, &ctx->inbufq, 0, &nread); if(!result) { - if(proxy_h2_process_pending_input(cf, data, &result) < 0) + if(proxy_h2_process_pending_input(cf, data)) /* immediate error, considered dead */ alive = FALSE; else { @@ -1580,7 +1565,7 @@ static CURLcode cf_h2_proxy_cntrl(struct Curl_cfilter *cf, struct Curl_cftype Curl_cft_h2_proxy = { "H2-PROXY", - CF_TYPE_IP_CONNECT|CF_TYPE_PROXY, + CF_TYPE_IP_CONNECT | CF_TYPE_PROXY, CURL_LOG_LVL_NONE, cf_h2_proxy_destroy, cf_h2_proxy_connect, @@ -1604,7 +1589,7 @@ CURLcode Curl_cf_h2_proxy_insert_after(struct Curl_cfilter *cf, CURLcode result = CURLE_OUT_OF_MEMORY; (void)data; - ctx = calloc(1, sizeof(*ctx)); + ctx = curlx_calloc(1, sizeof(*ctx)); if(!ctx) goto out; diff --git a/lib/cf-haproxy.c b/lib/cf-haproxy.c index 3231791097ed..ea35f040a33c 100644 --- a/lib/cf-haproxy.c +++ b/lib/cf-haproxy.c @@ -26,23 +26,17 @@ #ifndef CURL_DISABLE_PROXY -#include #include "urldata.h" #include "cfilters.h" #include "cf-haproxy.h" #include "curl_trc.h" -#include "multiif.h" #include "select.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - typedef enum { - HAPROXY_INIT, /* init/default/no tunnel state */ - HAPROXY_SEND, /* data_out being sent */ - HAPROXY_DONE /* all work done */ + HAPROXY_INIT, /* init/default/no tunnel state */ + HAPROXY_SEND, /* data_out being sent */ + HAPROXY_DONE /* all work done */ } haproxy_state; struct cf_haproxy_ctx { @@ -61,11 +55,11 @@ static void cf_haproxy_ctx_free(struct cf_haproxy_ctx *ctx) { if(ctx) { curlx_dyn_free(&ctx->data_out); - free(ctx); + curlx_free(ctx); } } -static CURLcode cf_haproxy_date_out_set(struct Curl_cfilter*cf, +static CURLcode cf_haproxy_date_out_set(struct Curl_cfilter *cf, struct Curl_easy *data) { struct cf_haproxy_ctx *ctx = cf->ctx; @@ -133,7 +127,7 @@ static CURLcode cf_haproxy_connect(struct Curl_cfilter *cf, if(len > 0) { size_t nwritten; result = Curl_conn_cf_send(cf->next, data, - curlx_dyn_ptr(&ctx->data_out), len, FALSE, + curlx_dyn_uptr(&ctx->data_out), len, FALSE, &nwritten); if(result) { if(result != CURLE_AGAIN) @@ -217,7 +211,7 @@ static CURLcode cf_haproxy_create(struct Curl_cfilter **pcf, CURLcode result; (void)data; - ctx = calloc(1, sizeof(*ctx)); + ctx = curlx_calloc(1, sizeof(*ctx)); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; diff --git a/lib/cf-haproxy.h b/lib/cf-haproxy.h index 9190dd5b578b..da9920fd89dd 100644 --- a/lib/cf-haproxy.h +++ b/lib/cf-haproxy.h @@ -25,6 +25,7 @@ ***************************************************************************/ #include "curl_setup.h" + #include "urldata.h" #ifndef CURL_DISABLE_PROXY diff --git a/lib/cf-https-connect.c b/lib/cf-https-connect.c index 5d6724dbc5e2..4882f28c4b26 100644 --- a/lib/cf-https-connect.c +++ b/lib/cf-https-connect.c @@ -27,7 +27,6 @@ #ifndef CURL_DISABLE_HTTP #include "urldata.h" -#include #include "curl_trc.h" #include "cfilters.h" #include "connect.h" @@ -35,13 +34,10 @@ #include "multiif.h" #include "cf-https-connect.h" #include "http2.h" +#include "progress.h" #include "select.h" #include "vquic/vquic.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - typedef enum { CF_HC_INIT, CF_HC_CONNECT, @@ -55,7 +51,7 @@ struct cf_hc_baller { CURLcode result; struct curltime started; int reply_ms; - unsigned char transport; + uint8_t transport; enum alpnid alpn_id; BIT(shutdown); }; @@ -124,7 +120,7 @@ struct cf_hc_ctx { static void cf_hc_baller_assign(struct cf_hc_baller *b, enum alpnid alpn_id, - unsigned char def_transport) + uint8_t def_transport) { b->alpn_id = alpn_id; b->transport = def_transport; @@ -148,12 +144,12 @@ static void cf_hc_baller_assign(struct cf_hc_baller *b, static void cf_hc_baller_init(struct cf_hc_baller *b, struct Curl_cfilter *cf, struct Curl_easy *data, - int transport) + uint8_t transport) { struct Curl_cfilter *save = cf->next; cf->next = NULL; - b->started = curlx_now(); + b->started = *Curl_pgrs_now(data); switch(b->alpn_id) { case ALPN_h3: transport = TRNSPRT_QUIC; @@ -215,12 +211,13 @@ static CURLcode baller_connected(struct Curl_cfilter *cf, reply_ms = cf_hc_baller_reply_ms(winner, data); if(reply_ms >= 0) CURL_TRC_CF(data, cf, "connect+handshake %s: %dms, 1st data: %dms", - winner->name, (int)curlx_timediff(curlx_now(), - winner->started), reply_ms); + winner->name, + (int)curlx_ptimediff_ms(Curl_pgrs_now(data), + &winner->started), reply_ms); else CURL_TRC_CF(data, cf, "deferred handshake %s: %dms", - winner->name, (int)curlx_timediff(curlx_now(), - winner->started)); + winner->name, (int)curlx_ptimediff_ms(Curl_pgrs_now(data), + &winner->started)); /* install the winning filter below this one. */ cf->next = winner->cf; @@ -247,7 +244,6 @@ static CURLcode baller_connected(struct Curl_cfilter *cf, return result; } - static bool time_to_start_next(struct Curl_cfilter *cf, struct Curl_easy *data, size_t idx, struct curltime now) @@ -269,7 +265,7 @@ static bool time_to_start_next(struct Curl_cfilter *cf, ctx->ballers[idx].name); return TRUE; } - elapsed_ms = curlx_timediff(now, ctx->started); + elapsed_ms = curlx_ptimediff_ms(&now, &ctx->started); if(elapsed_ms >= ctx->hard_eyeballs_timeout_ms) { CURL_TRC_CF(data, cf, "hard timeout of %" FMT_TIMEDIFF_T "ms reached, " "starting %s", @@ -297,7 +293,6 @@ static CURLcode cf_hc_connect(struct Curl_cfilter *cf, bool *done) { struct cf_hc_ctx *ctx = cf->ctx; - struct curltime now; CURLcode result = CURLE_OK; size_t i, failed_ballers; @@ -307,14 +302,13 @@ static CURLcode cf_hc_connect(struct Curl_cfilter *cf, } *done = FALSE; - now = curlx_now(); switch(ctx->state) { case CF_HC_INIT: DEBUGASSERT(!cf->next); for(i = 0; i < ctx->baller_count; i++) DEBUGASSERT(!ctx->ballers[i].cf); CURL_TRC_CF(data, cf, "connect, init"); - ctx->started = now; + ctx->started = *Curl_pgrs_now(data); cf_hc_baller_init(&ctx->ballers[0], cf, data, ctx->ballers[0].transport); if(ctx->baller_count > 1) { Curl_expire(data, ctx->soft_eyeballs_timeout_ms, EXPIRE_ALPN_EYEBALLS); @@ -333,7 +327,7 @@ static CURLcode cf_hc_connect(struct Curl_cfilter *cf, } } - if(time_to_start_next(cf, data, 1, now)) { + if(time_to_start_next(cf, data, 1, *Curl_pgrs_now(data))) { cf_hc_baller_init(&ctx->ballers[1], cf, data, ctx->ballers[1].transport); } @@ -474,7 +468,7 @@ static struct curltime cf_get_max_baller_time(struct Curl_cfilter *cf, struct Curl_cfilter *cfb = ctx->ballers[i].cf; memset(&t, 0, sizeof(t)); if(cfb && !cfb->cft->query(cfb, data, query, NULL, &t)) { - if((t.tv_sec || t.tv_usec) && curlx_timediff_us(t, tmax) > 0) + if((t.tv_sec || t.tv_usec) && curlx_ptimediff_us(&t, &tmax) > 0) tmax = t; } } @@ -580,27 +574,29 @@ struct Curl_cftype Curl_cft_http_connect = { static CURLcode cf_hc_create(struct Curl_cfilter **pcf, struct Curl_easy *data, enum alpnid *alpnids, size_t alpn_count, - unsigned char def_transport) + uint8_t def_transport) { struct Curl_cfilter *cf = NULL; struct cf_hc_ctx *ctx; CURLcode result = CURLE_OK; size_t i; + ctx = curlx_calloc(1, sizeof(*ctx)); + if(!ctx) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } + DEBUGASSERT(alpnids); DEBUGASSERT(alpn_count); DEBUGASSERT(alpn_count <= CURL_ARRAYSIZE(ctx->ballers)); if(!alpn_count || (alpn_count > CURL_ARRAYSIZE(ctx->ballers))) { failf(data, "https-connect filter create with unsupported %zu ALPN ids", alpn_count); - return CURLE_FAILED_INIT; - } - - ctx = calloc(1, sizeof(*ctx)); - if(!ctx) { - result = CURLE_OUT_OF_MEMORY; + result = CURLE_FAILED_INIT; goto out; } + for(i = 0; i < alpn_count; ++i) cf_hc_baller_assign(&ctx->ballers[i], alpnids[i], def_transport); for(; i < CURL_ARRAYSIZE(ctx->ballers); ++i) @@ -615,7 +611,7 @@ static CURLcode cf_hc_create(struct Curl_cfilter **pcf, out: *pcf = result ? NULL : cf; - free(ctx); + curlx_free(ctx); return result; } @@ -623,7 +619,7 @@ static CURLcode cf_http_connect_add(struct Curl_easy *data, struct connectdata *conn, int sockindex, enum alpnid *alpn_ids, size_t alpn_count, - unsigned char def_transport) + uint8_t def_transport) { struct Curl_cfilter *cf; CURLcode result = CURLE_OK; @@ -712,6 +708,31 @@ CURLcode Curl_cf_https_setup(struct Curl_easy *data, } #endif + /* Add preferred HTTP version ALPN first */ + if(data->state.http_neg.preferred && + (alpn_count < CURL_ARRAYSIZE(alpn_ids)) && + (data->state.http_neg.preferred & data->state.http_neg.allowed)) { + enum alpnid alpn_pref = ALPN_none; + switch(data->state.http_neg.preferred) { + case CURL_HTTP_V3x: + if(!Curl_conn_may_http3(data, conn, conn->transport_wanted)) + alpn_pref = ALPN_h3; + break; + case CURL_HTTP_V2x: + alpn_pref = ALPN_h2; + break; + case CURL_HTTP_V1x: + alpn_pref = ALPN_h1; + break; + default: + break; + } + if(alpn_pref && + !cf_https_alpns_contain(alpn_pref, alpn_ids, alpn_count)) { + alpn_ids[alpn_count++] = alpn_pref; + } + } + if((alpn_count < CURL_ARRAYSIZE(alpn_ids)) && (data->state.http_neg.wanted & CURL_HTTP_V3x) && !cf_https_alpns_contain(ALPN_h3, alpn_ids, alpn_count)) { diff --git a/lib/cf-https-connect.h b/lib/cf-https-connect.h index df51b62479d7..df29c8ddd7e1 100644 --- a/lib/cf-https-connect.h +++ b/lib/cf-https-connect.h @@ -44,6 +44,5 @@ CURLcode Curl_cf_https_setup(struct Curl_easy *data, struct connectdata *conn, int sockindex); - #endif /* !CURL_DISABLE_HTTP */ #endif /* HEADER_CURL_CF_HTTP_H */ diff --git a/lib/cf-ip-happy.c b/lib/cf-ip-happy.c index 6b7130be83f5..36d53ed9c234 100644 --- a/lib/cf-ip-happy.c +++ b/lib/cf-ip-happy.c @@ -27,9 +27,6 @@ #ifdef HAVE_NETINET_IN_H #include /* may need it */ #endif -#ifdef HAVE_SYS_UN_H -#include /* for sockaddr_un */ -#endif #ifdef HAVE_LINUX_TCP_H #include #elif defined(HAVE_NETINET_TCP_H) @@ -60,13 +57,9 @@ #include "select.h" #include "vquic/vquic.h" /* for quic cfilters */ -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - struct transport_provider { - int transport; + uint8_t transport; cf_ip_connect_create *cf_create; }; @@ -87,7 +80,7 @@ struct transport_provider transport_providers[] = { #endif }; -static cf_ip_connect_create *get_cf_create(int transport) +static cf_ip_connect_create *get_cf_create(uint8_t transport) { size_t i; for(i = 0; i < CURL_ARRAYSIZE(transport_providers); ++i) { @@ -99,7 +92,7 @@ static cf_ip_connect_create *get_cf_create(int transport) #ifdef UNITTESTS /* used by unit2600.c */ -void Curl_debug_set_transport_provider(int transport, +void Curl_debug_set_transport_provider(uint8_t transport, cf_ip_connect_create *cf_create) { size_t i; @@ -112,7 +105,6 @@ void Curl_debug_set_transport_provider(int transport, } #endif /* UNITTESTS */ - struct cf_ai_iter { const struct Curl_addrinfo *head; const struct Curl_addrinfo *last; @@ -172,7 +164,7 @@ struct cf_ip_attempt { struct curltime started; /* start of current attempt */ CURLcode result; int ai_family; - int transport; + uint8_t transport; int error; BIT(connected); /* cf has connected */ BIT(shutdown); /* cf has shutdown */ @@ -186,7 +178,7 @@ static void cf_ip_attempt_free(struct cf_ip_attempt *a, if(a) { if(a->cf) Curl_conn_cf_discard_chain(&a->cf, data); - free(a); + curlx_free(a); } } @@ -195,7 +187,7 @@ static CURLcode cf_ip_attempt_new(struct cf_ip_attempt **pa, struct Curl_easy *data, const struct Curl_addrinfo *addr, int ai_family, - int transport, + uint8_t transport, cf_ip_connect_create *cf_create) { struct Curl_cfilter *wcf; @@ -203,7 +195,7 @@ static CURLcode cf_ip_attempt_new(struct cf_ip_attempt **pa, CURLcode result = CURLE_OK; *pa = NULL; - a = calloc(1, sizeof(*a)); + a = curlx_calloc(1, sizeof(*a)); if(!a) return CURLE_OUT_OF_MEMORY; @@ -237,7 +229,7 @@ static CURLcode cf_ip_attempt_connect(struct cf_ip_attempt *a, bool *connected) { *connected = a->connected; - if(!a->result && !*connected) { + if(!a->result && !*connected) { /* evaluate again */ a->result = Curl_conn_cf_connect(a->cf, data, connected); @@ -264,7 +256,7 @@ struct cf_ip_ballers { struct curltime last_attempt_started; timediff_t attempt_delay_ms; int last_attempt_ai_family; - int transport; + uint8_t transport; }; static CURLcode cf_ip_attempt_restart(struct cf_ip_attempt *a, @@ -315,7 +307,7 @@ static void cf_ip_ballers_clear(struct Curl_cfilter *cf, static CURLcode cf_ip_ballers_init(struct cf_ip_ballers *bs, int ip_version, const struct Curl_addrinfo *addr_list, cf_ip_connect_create *cf_create, - int transport, + uint8_t transport, timediff_t attempt_delay_ms) { memset(bs, 0, sizeof(*bs)); @@ -358,7 +350,6 @@ static CURLcode cf_ip_ballers_run(struct cf_ip_ballers *bs, CURLcode result = CURLE_OK; struct cf_ip_attempt *a = NULL, **panchor; bool do_more; - struct curltime now; timediff_t next_expire_ms; int i, inconclusive, ongoing; @@ -366,7 +357,6 @@ static CURLcode cf_ip_ballers_run(struct cf_ip_ballers *bs, return CURLE_OK; evaluate: - now = curlx_now(); ongoing = inconclusive = 0; /* check if a running baller connects now */ @@ -403,7 +393,7 @@ static CURLcode cf_ip_ballers_run(struct cf_ip_ballers *bs, /* no attempt connected yet, start another one? */ if(!ongoing) { if(!bs->started.tv_sec && !bs->started.tv_usec) - bs->started = now; + bs->started = *Curl_pgrs_now(data); do_more = TRUE; } else { @@ -413,8 +403,8 @@ static CURLcode cf_ip_ballers_run(struct cf_ip_ballers *bs, more_possible = cf_ai_iter_has_more(&bs->ipv6_iter); #endif do_more = more_possible && - (curlx_timediff(now, bs->last_attempt_started) >= - bs->attempt_delay_ms); + (curlx_ptimediff_ms(Curl_pgrs_now(data), &bs->last_attempt_started) >= + bs->attempt_delay_ms); if(do_more) CURL_TRC_CF(data, cf, "happy eyeballs timeout expired, " "start next attempt"); @@ -427,9 +417,9 @@ static CURLcode cf_ip_ballers_run(struct cf_ip_ballers *bs, int ai_family = 0; #ifdef USE_IPV6 if((bs->last_attempt_ai_family == AF_INET) || - !cf_ai_iter_has_more(&bs->addr_iter)) { - addr = cf_ai_iter_next(&bs->ipv6_iter); - ai_family = bs->ipv6_iter.ai_family; + !cf_ai_iter_has_more(&bs->addr_iter)) { + addr = cf_ai_iter_next(&bs->ipv6_iter); + ai_family = bs->ipv6_iter.ai_family; } #endif if(!addr) { @@ -452,7 +442,7 @@ static CURLcode cf_ip_ballers_run(struct cf_ip_ballers *bs, while(*panchor) panchor = &((*panchor)->next); *panchor = a; - bs->last_attempt_started = now; + bs->last_attempt_started = *Curl_pgrs_now(data); bs->last_attempt_ai_family = ai_family; /* and run everything again */ goto evaluate; @@ -460,7 +450,8 @@ static CURLcode cf_ip_ballers_run(struct cf_ip_ballers *bs, else if(inconclusive) { /* tried all addresses, no success but some where inconclusive. * Let's restart the inconclusive ones. */ - timediff_t since_ms = curlx_timediff(now, bs->last_attempt_started); + timediff_t since_ms = + curlx_ptimediff_ms(Curl_pgrs_now(data), &bs->last_attempt_started); timediff_t delay_ms = bs->attempt_delay_ms - since_ms; if(delay_ms <= 0) { CURL_TRC_CF(data, cf, "all attempts inconclusive, restarting one"); @@ -473,7 +464,7 @@ static CURLcode cf_ip_ballers_run(struct cf_ip_ballers *bs, CURL_TRC_CF(data, cf, "restarted baller %d -> %d", i, result); if(result) /* serious failure */ goto out; - bs->last_attempt_started = now; + bs->last_attempt_started = *Curl_pgrs_now(data); goto evaluate; } DEBUGASSERT(0); /* should not come here */ @@ -505,10 +496,11 @@ static CURLcode cf_ip_ballers_run(struct cf_ip_ballers *bs, bool more_possible; /* when do we need to be called again? */ - next_expire_ms = Curl_timeleft(data, &now, TRUE); + next_expire_ms = Curl_timeleft_ms(data, TRUE); if(next_expire_ms <= 0) { failf(data, "Connection timeout after %" FMT_OFF_T " ms", - curlx_timediff(now, data->progress.t_startsingle)); + curlx_ptimediff_ms(Curl_pgrs_now(data), + &data->progress.t_startsingle)); return CURLE_OPERATION_TIMEDOUT; } @@ -519,7 +511,8 @@ static CURLcode cf_ip_ballers_run(struct cf_ip_ballers *bs, #endif if(more_possible) { timediff_t expire_ms, elapsed_ms; - elapsed_ms = curlx_timediff(now, bs->last_attempt_started); + elapsed_ms = + curlx_ptimediff_ms(Curl_pgrs_now(data), &bs->last_attempt_started); expire_ms = CURLMAX(bs->attempt_delay_ms - elapsed_ms, 0); next_expire_ms = CURLMIN(next_expire_ms, expire_ms); if(next_expire_ms <= 0) { @@ -595,7 +588,7 @@ static struct curltime cf_ip_ballers_max_time(struct cf_ip_ballers *bs, for(a = bs->running; a; a = a->next) { memset(&t, 0, sizeof(t)); if(!a->cf->cft->query(a->cf, data, query, NULL, &t)) { - if((t.tv_sec || t.tv_usec) && curlx_timediff_us(t, tmax) > 0) + if((t.tv_sec || t.tv_usec) && curlx_ptimediff_us(&t, &tmax) > 0) tmax = t; } } @@ -618,7 +611,6 @@ static int cf_ip_ballers_min_reply_ms(struct cf_ip_ballers *bs, return reply_ms; } - typedef enum { SCFST_INIT, SCFST_WAITING, @@ -626,14 +618,13 @@ typedef enum { } cf_connect_state; struct cf_ip_happy_ctx { - int transport; + uint8_t transport; cf_ip_connect_create *cf_create; cf_connect_state state; struct cf_ip_ballers ballers; struct curltime started; }; - static CURLcode is_connected(struct Curl_cfilter *cf, struct Curl_easy *data, bool *connected) @@ -682,7 +673,8 @@ static CURLcode is_connected(struct Curl_cfilter *cf, proxy_name ? "via " : "", proxy_name ? proxy_name : "", proxy_name ? " " : "", - curlx_timediff(curlx_now(), data->progress.t_startsingle), + curlx_ptimediff_ms(Curl_pgrs_now(data), + &data->progress.t_startsingle), curl_easy_strerror(result)); } @@ -707,14 +699,14 @@ static CURLcode start_connect(struct Curl_cfilter *cf, if(!dns) return CURLE_FAILED_INIT; - if(Curl_timeleft(data, NULL, TRUE) < 0) { + if(Curl_timeleft_ms(data, TRUE) < 0) { /* a precaution, no need to continue if time already is up */ failf(data, "Connection time-out"); return CURLE_OPERATION_TIMEDOUT; } - CURL_TRC_CF(data, cf, "init ip ballers for transport %d", ctx->transport); - ctx->started = curlx_now(); + CURL_TRC_CF(data, cf, "init ip ballers for transport %u", ctx->transport); + ctx->started = *Curl_pgrs_now(data); return cf_ip_ballers_init(&ctx->ballers, cf->conn->ip_version, dns->addr, ctx->cf_create, ctx->transport, data->set.happy_eyeballs_timeout); @@ -778,50 +770,50 @@ static CURLcode cf_ip_happy_connect(struct Curl_cfilter *cf, *done = FALSE; switch(ctx->state) { - case SCFST_INIT: - DEBUGASSERT(CURL_SOCKET_BAD == Curl_conn_cf_get_socket(cf, data)); - DEBUGASSERT(!cf->connected); - result = start_connect(cf, data); - if(result) - return result; - ctx->state = SCFST_WAITING; - FALLTHROUGH(); - case SCFST_WAITING: - result = is_connected(cf, data, done); - if(!result && *done) { - DEBUGASSERT(ctx->ballers.winner); - DEBUGASSERT(ctx->ballers.winner->cf); - DEBUGASSERT(ctx->ballers.winner->cf->connected); - /* we have a winner. Install and activate it. - * close/free all others. */ - ctx->state = SCFST_DONE; - cf->connected = TRUE; - cf->next = ctx->ballers.winner->cf; - ctx->ballers.winner->cf = NULL; - cf_ip_happy_ctx_clear(cf, data); - Curl_expire_done(data, EXPIRE_HAPPY_EYEBALLS); - - if(cf->conn->handler->protocol & PROTO_FAMILY_SSH) - Curl_pgrsTime(data, TIMER_APPCONNECT); /* we are connected already */ + case SCFST_INIT: + DEBUGASSERT(CURL_SOCKET_BAD == Curl_conn_cf_get_socket(cf, data)); + DEBUGASSERT(!cf->connected); + result = start_connect(cf, data); + if(result) + return result; + ctx->state = SCFST_WAITING; + FALLTHROUGH(); + case SCFST_WAITING: + result = is_connected(cf, data, done); + if(!result && *done) { + DEBUGASSERT(ctx->ballers.winner); + DEBUGASSERT(ctx->ballers.winner->cf); + DEBUGASSERT(ctx->ballers.winner->cf->connected); + /* we have a winner. Install and activate it. + * close/free all others. */ + ctx->state = SCFST_DONE; + cf->connected = TRUE; + cf->next = ctx->ballers.winner->cf; + ctx->ballers.winner->cf = NULL; + cf_ip_happy_ctx_clear(cf, data); + Curl_expire_done(data, EXPIRE_HAPPY_EYEBALLS); + + if(cf->conn->handler->protocol & PROTO_FAMILY_SSH) + Curl_pgrsTime(data, TIMER_APPCONNECT); /* we are connected already */ #ifndef CURL_DISABLE_VERBOSE_STRINGS - if(Curl_trc_cf_is_verbose(cf, data)) { - struct ip_quadruple ipquad; - bool is_ipv6; - if(!Curl_conn_cf_get_ip_info(cf->next, data, &is_ipv6, &ipquad)) { - const char *host; - int port; - Curl_conn_get_current_host(data, cf->sockindex, &host, &port); - CURL_TRC_CF(data, cf, "Connected to %s (%s) port %u", - host, ipquad.remote_ip, ipquad.remote_port); - } + if(Curl_trc_cf_is_verbose(cf, data)) { + struct ip_quadruple ipquad; + bool is_ipv6; + if(!Curl_conn_cf_get_ip_info(cf->next, data, &is_ipv6, &ipquad)) { + const char *host; + int port; + Curl_conn_get_current_host(data, cf->sockindex, &host, &port); + CURL_TRC_CF(data, cf, "Connected to %s (%s) port %u", + host, ipquad.remote_ip, ipquad.remote_port); } -#endif - data->info.numconnects++; /* to track the # of connections made */ } - break; - case SCFST_DONE: - *done = TRUE; - break; +#endif + data->info.numconnects++; /* to track the # of connections made */ + } + break; + case SCFST_DONE: + *done = TRUE; + break; } return result; } @@ -933,7 +925,7 @@ static CURLcode cf_ip_happy_create(struct Curl_cfilter **pcf, struct Curl_easy *data, struct connectdata *conn, cf_ip_connect_create *cf_create, - int transport) + uint8_t transport) { struct cf_ip_happy_ctx *ctx = NULL; CURLcode result; @@ -941,7 +933,7 @@ static CURLcode cf_ip_happy_create(struct Curl_cfilter **pcf, (void)data; (void)conn; *pcf = NULL; - ctx = calloc(1, sizeof(*ctx)); + ctx = curlx_calloc(1, sizeof(*ctx)); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -954,14 +946,14 @@ static CURLcode cf_ip_happy_create(struct Curl_cfilter **pcf, out: if(result) { Curl_safefree(*pcf); - free(ctx); + curlx_free(ctx); } return result; } CURLcode cf_ip_happy_insert_after(struct Curl_cfilter *cf_at, struct Curl_easy *data, - int transport) + uint8_t transport) { cf_ip_connect_create *cf_create; struct Curl_cfilter *cf; @@ -971,7 +963,7 @@ CURLcode cf_ip_happy_insert_after(struct Curl_cfilter *cf_at, DEBUGASSERT(cf_at); cf_create = get_cf_create(transport); if(!cf_create) { - CURL_TRC_CF(data, cf_at, "unsupported transport type %d", transport); + CURL_TRC_CF(data, cf_at, "unsupported transport type %u", transport); return CURLE_UNSUPPORTED_PROTOCOL; } result = cf_ip_happy_create(&cf, data, cf_at->conn, cf_create, transport); diff --git a/lib/cf-ip-happy.h b/lib/cf-ip-happy.h index 96e619ae4303..71f212250fa0 100644 --- a/lib/cf-ip-happy.h +++ b/lib/cf-ip-happy.h @@ -25,9 +25,6 @@ ***************************************************************************/ #include "curl_setup.h" -#include "curlx/nonblock.h" /* for curlx_nonblock() */ -#include "sockaddr.h" - /** * Create a cfilter for making an "ip" connection to the * given address, using parameters from `conn`. The "ip" connection @@ -43,16 +40,16 @@ typedef CURLcode cf_ip_connect_create(struct Curl_cfilter **pcf, struct Curl_easy *data, struct connectdata *conn, const struct Curl_addrinfo *ai, - int transport); + uint8_t transport); CURLcode cf_ip_happy_insert_after(struct Curl_cfilter *cf_at, struct Curl_easy *data, - int transport); + uint8_t transport); extern struct Curl_cftype Curl_cft_ip_happy; #ifdef UNITTESTS -void Curl_debug_set_transport_provider(int transport, +void Curl_debug_set_transport_provider(uint8_t transport, cf_ip_connect_create *cf_create); #endif diff --git a/lib/cf-socket.c b/lib/cf-socket.c index 758641e40dbe..ab28bc40aabb 100644 --- a/lib/cf-socket.c +++ b/lib/cf-socket.c @@ -27,9 +27,6 @@ #ifdef HAVE_NETINET_IN_H #include /* may need it */ #endif -#ifdef HAVE_SYS_UN_H -#include /* for sockaddr_un */ -#endif #ifdef HAVE_LINUX_TCP_H #include #elif defined(HAVE_NETINET_TCP_H) @@ -60,61 +57,41 @@ #include "urldata.h" #include "bufq.h" -#include "sendf.h" +#include "curl_trc.h" #include "if2ip.h" #include "cfilters.h" #include "cf-socket.h" #include "connect.h" #include "select.h" -#include "url.h" /* for Curl_safefree() */ #include "multiif.h" -#include "sockaddr.h" /* required for Curl_sockaddr_storage */ #include "curlx/inet_pton.h" #include "progress.h" -#include "curlx/warnless.h" #include "conncache.h" #include "multihandle.h" #include "rand.h" -#include "share.h" #include "strdup.h" #include "system_win32.h" +#include "curlx/nonblock.h" #include "curlx/version_win32.h" #include "curlx/strerr.h" #include "curlx/strparse.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - -#if defined(USE_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; - * DragonFly BSD: acts like off, and dummy setting; - * OpenBSD and earlier Windows: unsupported. - * Linux: controlled by /proc/sys/net/ipv6/bindv6only. - */ -static void set_ipv6_v6only(curl_socket_t sockfd, int on) -{ - (void)setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&on, sizeof(on)); -} -#else -#define set_ipv6_v6only(x,y) -#endif - -static void tcpnodelay(struct Curl_easy *data, curl_socket_t sockfd) +static void tcpnodelay(struct Curl_cfilter *cf, + struct Curl_easy *data, + curl_socket_t sockfd) { #if defined(TCP_NODELAY) && defined(CURL_TCP_NODELAY_SUPPORTED) - curl_socklen_t onoff = (curl_socklen_t) 1; + curl_socklen_t onoff = (curl_socklen_t)1; int level = IPPROTO_TCP; char buffer[STRERROR_LEN]; if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff, sizeof(onoff)) < 0) - infof(data, "Could not set TCP_NODELAY: %s", - curlx_strerror(SOCKERRNO, buffer, sizeof(buffer))); + CURL_TRC_CF(data, cf, "Could not set TCP_NODELAY: %s", + curlx_strerror(SOCKERRNO, buffer, sizeof(buffer))); #else + (void)cf; (void)data; (void)sockfd; #endif @@ -125,31 +102,28 @@ static void tcpnodelay(struct Curl_easy *data, curl_socket_t sockfd) sending data to a dead peer (instead of relying on the 4th argument to send being MSG_NOSIGNAL). Possibly also existing and in use on other BSD systems? */ -static void nosigpipe(struct Curl_easy *data, +static void nosigpipe(struct Curl_cfilter *cf, + 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) { #ifndef CURL_DISABLE_VERBOSE_STRINGS char buffer[STRERROR_LEN]; - infof(data, "Could not set SO_NOSIGPIPE: %s", - curlx_strerror(SOCKERRNO, buffer, sizeof(buffer))); + CURL_TRC_CF(data, cf, "Could not set SO_NOSIGPIPE: %s", + curlx_strerror(SOCKERRNO, buffer, sizeof(buffer))); +#else + (void)cf; + (void)data; #endif } } #else -#define nosigpipe(x,y) Curl_nop_stmt +#define nosigpipe(x, y, z) Curl_nop_stmt #endif -#if defined(USE_WINSOCK) && \ - defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL) && defined(TCP_KEEPCNT) -/* Win 10, v 1709 (10.0.16299) and later can use SetSockOpt TCP_KEEP____ - * so should use seconds */ -#define CURL_WINSOCK_KEEP_SSO -#define KEEPALIVE_FACTOR(x) -#elif defined(USE_WINSOCK) || \ +#if defined(USE_WINSOCK) || \ (defined(__sun) && !defined(TCP_KEEPIDLE)) || \ (defined(__DragonFly__) && __DragonFly_version < 500702) || \ (defined(_WIN32) && !defined(TCP_KEEPIDLE)) @@ -160,82 +134,91 @@ static void nosigpipe(struct Curl_easy *data, #define KEEPALIVE_FACTOR(x) #endif -/* Offered by mingw-w64 and MS SDK. Latter only when targeting Win7+. */ -#if defined(USE_WINSOCK) && !defined(SIO_KEEPALIVE_VALS) -#define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4) - -struct tcp_keepalive { - u_long onoff; - u_long keepalivetime; - u_long keepaliveinterval; -}; -#endif - -static void -tcpkeepalive(struct Curl_easy *data, - curl_socket_t sockfd) +static void tcpkeepalive(struct Curl_cfilter *cf, + struct Curl_easy *data, + curl_socket_t sockfd) { int optval = data->set.tcp_keepalive ? 1 : 0; /* 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 " - "%" FMT_SOCKET_T ": errno %d", - sockfd, SOCKERRNO); + CURL_TRC_CF(data, cf, "Failed to set SO_KEEPALIVE on fd " + "%" FMT_SOCKET_T ": errno %d", sockfd, SOCKERRNO); } else { -#ifdef SIO_KEEPALIVE_VALS /* Windows */ -/* Windows 10, version 1709 (10.0.16299) and later versions */ -#ifdef CURL_WINSOCK_KEEP_SSO - optval = curlx_sltosi(data->set.tcp_keepidle); - KEEPALIVE_FACTOR(optval); - if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, - (const char *)&optval, sizeof(optval)) < 0) { - infof(data, "Failed to set TCP_KEEPIDLE on fd " - "%" FMT_SOCKET_T ": errno %d", - sockfd, SOCKERRNO); - } - optval = curlx_sltosi(data->set.tcp_keepintvl); - KEEPALIVE_FACTOR(optval); - if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL, - (const char *)&optval, sizeof(optval)) < 0) { - infof(data, "Failed to set TCP_KEEPINTVL on fd " - "%" FMT_SOCKET_T ": errno %d", - sockfd, SOCKERRNO); - } - optval = curlx_sltosi(data->set.tcp_keepcnt); - if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPCNT, - (const char *)&optval, sizeof(optval)) < 0) { - infof(data, "Failed to set TCP_KEEPCNT on fd " - "%" FMT_SOCKET_T ": errno %d", - sockfd, SOCKERRNO); +#ifdef USE_WINSOCK + /* Windows 10, version 1709 (10.0.16299) and later versions can use + setsockopt() TCP_KEEP*. Older versions return with failure. */ + if(curlx_verify_windows_version(10, 0, 16299, PLATFORM_WINNT, + VERSION_GREATER_THAN_EQUAL)) { + CURL_TRC_CF(data, cf, "Set TCP_KEEP* on fd=%" FMT_SOCKET_T, sockfd); + optval = curlx_sltosi(data->set.tcp_keepidle); +/* Offered by mingw-w64 v12+. MS SDK 6.0A+. */ +#ifndef TCP_KEEPALIVE +#define TCP_KEEPALIVE 3 +#endif +/* Offered by mingw-w64 v12+. MS SDK ~10+/~VS2017+. */ +#ifndef TCP_KEEPCNT +#define TCP_KEEPCNT 16 +#endif +#ifndef TCP_KEEPIDLE +#define TCP_KEEPIDLE TCP_KEEPALIVE +#endif +#ifndef TCP_KEEPINTVL +#define TCP_KEEPINTVL 17 +#endif + if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, + (const char *)&optval, sizeof(optval)) < 0) { + CURL_TRC_CF(data, cf, "Failed to set TCP_KEEPIDLE on fd " + "%" FMT_SOCKET_T ": errno %d", sockfd, SOCKERRNO); + } + optval = curlx_sltosi(data->set.tcp_keepintvl); + if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL, + (const char *)&optval, sizeof(optval)) < 0) { + CURL_TRC_CF(data, cf, "Failed to set TCP_KEEPINTVL on fd " + "%" FMT_SOCKET_T ": errno %d", sockfd, SOCKERRNO); + } + optval = curlx_sltosi(data->set.tcp_keepcnt); + if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPCNT, + (const char *)&optval, sizeof(optval)) < 0) { + CURL_TRC_CF(data, cf, "Failed to set TCP_KEEPCNT on fd " + "%" FMT_SOCKET_T ": errno %d", sockfd, SOCKERRNO); + } } -#else /* Windows < 10.0.16299 */ - struct tcp_keepalive vals; - DWORD dummy; - vals.onoff = 1; - optval = curlx_sltosi(data->set.tcp_keepidle); - KEEPALIVE_FACTOR(optval); - vals.keepalivetime = (u_long)optval; - optval = curlx_sltosi(data->set.tcp_keepintvl); - KEEPALIVE_FACTOR(optval); - vals.keepaliveinterval = (u_long)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 " - "%" FMT_SOCKET_T ": errno %d", sockfd, SOCKERRNO); + else { +/* Offered by mingw-w64 and MS SDK. Latter only when targeting Win7+. */ +#ifndef SIO_KEEPALIVE_VALS +#define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR, 4) + struct tcp_keepalive { + u_long onoff; + u_long keepalivetime; + u_long keepaliveinterval; + }; +#endif + struct tcp_keepalive vals; + DWORD dummy; + vals.onoff = 1; + optval = curlx_sltosi(data->set.tcp_keepidle); + KEEPALIVE_FACTOR(optval); + vals.keepalivetime = (u_long)optval; + optval = curlx_sltosi(data->set.tcp_keepintvl); + KEEPALIVE_FACTOR(optval); + vals.keepaliveinterval = (u_long)optval; + if(WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID)&vals, sizeof(vals), + NULL, 0, &dummy, NULL, NULL) != 0) { + CURL_TRC_CF(data, cf, "Failed to set SIO_KEEPALIVE_VALS on fd " + "%" FMT_SOCKET_T ": errno %d", sockfd, SOCKERRNO); + } } -#endif -#else /* !Windows */ +#else /* !USE_WINSOCK */ #ifdef TCP_KEEPIDLE optval = curlx_sltosi(data->set.tcp_keepidle); KEEPALIVE_FACTOR(optval); if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, (void *)&optval, sizeof(optval)) < 0) { - infof(data, "Failed to set TCP_KEEPIDLE on fd " - "%" FMT_SOCKET_T ": errno %d", - sockfd, SOCKERRNO); + CURL_TRC_CF(data, cf, "Failed to set TCP_KEEPIDLE on fd " + "%" FMT_SOCKET_T ": errno %d", sockfd, SOCKERRNO); } #elif defined(TCP_KEEPALIVE) /* macOS style */ @@ -243,9 +226,8 @@ 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 " - "%" FMT_SOCKET_T ": errno %d", - sockfd, SOCKERRNO); + CURL_TRC_CF(data, cf, "Failed to set TCP_KEEPALIVE on fd " + "%" FMT_SOCKET_T ": errno %d", sockfd, SOCKERRNO); } #elif defined(TCP_KEEPALIVE_THRESHOLD) /* Solaris <11.4 style */ @@ -253,9 +235,8 @@ tcpkeepalive(struct Curl_easy *data, KEEPALIVE_FACTOR(optval); if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE_THRESHOLD, (void *)&optval, sizeof(optval)) < 0) { - infof(data, "Failed to set TCP_KEEPALIVE_THRESHOLD on fd " - "%" FMT_SOCKET_T ": errno %d", - sockfd, SOCKERRNO); + CURL_TRC_CF(data, cf, "Failed to set TCP_KEEPALIVE_THRESHOLD on fd " + "%" FMT_SOCKET_T ": errno %d", sockfd, SOCKERRNO); } #endif #ifdef TCP_KEEPINTVL @@ -263,9 +244,8 @@ 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 " - "%" FMT_SOCKET_T ": errno %d", - sockfd, SOCKERRNO); + CURL_TRC_CF(data, cf, "Failed to set TCP_KEEPINTVL on fd " + "%" FMT_SOCKET_T ": errno %d", sockfd, SOCKERRNO); } #elif defined(TCP_KEEPALIVE_ABORT_THRESHOLD) /* Solaris <11.4 style */ @@ -284,19 +264,19 @@ tcpkeepalive(struct Curl_easy *data, KEEPALIVE_FACTOR(optval); if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE_ABORT_THRESHOLD, (void *)&optval, sizeof(optval)) < 0) { - infof(data, "Failed to set TCP_KEEPALIVE_ABORT_THRESHOLD on fd " - "%" FMT_SOCKET_T ": errno %d", sockfd, SOCKERRNO); + CURL_TRC_CF(data, cf, "Failed to set TCP_KEEPALIVE_ABORT_THRESHOLD" + " on fd %" FMT_SOCKET_T ": errno %d", sockfd, SOCKERRNO); } #endif #ifdef TCP_KEEPCNT optval = curlx_sltosi(data->set.tcp_keepcnt); if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPCNT, (void *)&optval, sizeof(optval)) < 0) { - infof(data, "Failed to set TCP_KEEPCNT on fd " - "%" FMT_SOCKET_T ": errno %d", sockfd, SOCKERRNO); + CURL_TRC_CF(data, cf, "Failed to set TCP_KEEPCNT on fd " + "%" FMT_SOCKET_T ": errno %d", sockfd, SOCKERRNO); } #endif -#endif +#endif /* USE_WINSOCK */ } } @@ -306,7 +286,7 @@ tcpkeepalive(struct Curl_easy *data, */ static CURLcode sock_assign_addr(struct Curl_sockaddr_ex *dest, const struct Curl_addrinfo *ai, - int transport) + uint8_t transport) { /* * The Curl_sockaddr_ex structure is basically libcurl's external API @@ -344,18 +324,20 @@ static CURLcode socket_open(struct Curl_easy *data, struct Curl_sockaddr_ex *addr, curl_socket_t *sockfd) { + char errbuf[STRERROR_LEN]; + DEBUGASSERT(data); DEBUGASSERT(data->conn); if(data->set.fopensocket) { - /* - * If the opensocket callback is set, all the destination address - * information is passed to the callback. Depending on this information the - * callback may opt to abort the connection, this is indicated returning - * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When - * the callback returns a valid socket the destination address information - * might have been changed and this 'new' address will actually be used - * here to connect. - */ + /* + * If the opensocket callback is set, all the destination address + * information is passed to the callback. Depending on this information the + * callback may opt to abort the connection, this is indicated returning + * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When + * the callback returns a valid socket the destination address information + * might have been changed and this 'new' address will actually be used + * here to connect. + */ Curl_set_in_callback(data, TRUE); *sockfd = data->set.fopensocket(data->set.opensocket_client, CURLSOCKTYPE_IPCXN, @@ -367,13 +349,15 @@ static CURLcode socket_open(struct Curl_easy *data, *sockfd = CURL_SOCKET(addr->family, addr->socktype, addr->protocol); } - if(*sockfd == CURL_SOCKET_BAD) + if(*sockfd == CURL_SOCKET_BAD) { /* no socket, no connection */ + failf(data, "failed to open socket: %s", + curlx_strerror(SOCKERRNO, errbuf, sizeof(errbuf))); return CURLE_COULDNT_CONNECT; + } #ifdef HAVE_FCNTL if(fcntl(*sockfd, F_SETFD, FD_CLOEXEC) < 0) { - char errbuf[STRERROR_LEN]; failf(data, "fcntl set CLOEXEC: %s", curlx_strerror(SOCKERRNO, errbuf, sizeof(errbuf))); close(*sockfd); @@ -403,7 +387,7 @@ static CURLcode socket_open(struct Curl_easy *data, CURLcode Curl_socket_open(struct Curl_easy *data, const struct Curl_addrinfo *ai, struct Curl_sockaddr_ex *addr, - int transport, + uint8_t transport, curl_socket_t *sockfd) { struct Curl_sockaddr_ex dummy; @@ -554,7 +538,7 @@ CURLcode Curl_parse_interface(const char *input, ++host_part; *host = Curl_memdup0(host_part, len - (host_part - input)); if(!*host) { - free(*iface); + curlx_free(*iface); *iface = NULL; return CURLE_OUT_OF_MEMORY; } @@ -603,7 +587,7 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn, if(!iface && !host && !port) /* no local kind of binding was requested */ return CURLE_OK; - else if(iface && (strlen(iface) >= 255) ) + else if(iface && (strlen(iface) >= 255)) return CURLE_BAD_FUNCTION_ARGUMENT; memset(&sa, 0, sizeof(struct Curl_sockaddr_storage)); @@ -643,33 +627,33 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn, /* Discover IP from input device, then bind to it */ if2ip_result = Curl_if2ip(af, #ifdef USE_IPV6 - scope, conn->scope_id, + scope, conn->scope_id, #endif - iface, myhost, sizeof(myhost)); + iface, myhost, sizeof(myhost)); } switch(if2ip_result) { - case IF2IP_NOT_FOUND: - if(iface_input && !host_input) { - /* Do not fall back to treating it as a hostname */ - char buffer[STRERROR_LEN]; - data->state.os_errno = error = SOCKERRNO; - failf(data, "Couldn't bind to interface '%s' with errno %d: %s", - iface, error, curlx_strerror(error, buffer, sizeof(buffer))); - return CURLE_INTERFACE_FAILED; - } - break; - case IF2IP_AF_NOT_SUPPORTED: - /* Signal the caller to try another address family if available */ - return CURLE_UNSUPPORTED_PROTOCOL; - case IF2IP_FOUND: - /* - * We now have the numerical IP address in the 'myhost' buffer - */ - host = myhost; - infof(data, "Local Interface %s is ip %s using address family %i", - iface, host, af); - done = 1; - break; + case IF2IP_NOT_FOUND: + if(iface_input && !host_input) { + /* Do not fall back to treating it as a hostname */ + char buffer[STRERROR_LEN]; + data->state.os_errno = error = SOCKERRNO; + failf(data, "Could not bind to interface '%s' with errno %d: %s", + iface, error, curlx_strerror(error, buffer, sizeof(buffer))); + return CURLE_INTERFACE_FAILED; + } + break; + case IF2IP_AF_NOT_SUPPORTED: + /* Signal the caller to try another address family if available */ + return CURLE_UNSUPPORTED_PROTOCOL; + case IF2IP_FOUND: + /* + * We now have the numerical IP address in the 'myhost' buffer + */ + host = myhost; + infof(data, "Local Interface %s is ip %s using address family %i", + iface, host, af); + done = 1; + break; } if(!iface_input || host_input) { /* @@ -731,7 +715,7 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn, present, is known to be numeric */ curl_off_t scope_id; if(curlx_str_number((const char **)CURL_UNCONST(&scope_ptr), - &scope_id, UINT_MAX)) + &scope_id, UINT_MAX)) return CURLE_UNSUPPORTED_PROTOCOL; si6->sin6_scope_id = (unsigned int)scope_id; } @@ -757,7 +741,7 @@ static CURLcode bindlocal(struct Curl_easy *data, struct connectdata *conn, char buffer[STRERROR_LEN]; data->state.errorbuf = FALSE; data->state.os_errno = error = SOCKERRNO; - failf(data, "Couldn't bind to '%s' with errno %d: %s", host, + failf(data, "Could not bind to '%s' with errno %d: %s", host, error, curlx_strerror(error, buffer, sizeof(buffer))); return CURLE_INTERFACE_FAILED; } @@ -842,24 +826,11 @@ static bool verifyconnect(curl_socket_t sockfd, int *error) * * Someone got to verify this on Win-NT 4.0, 2000." */ - -#ifdef UNDER_CE - Sleep(0); -#else SleepEx(0, FALSE); -#endif - #endif if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize)) err = SOCKERRNO; -#ifdef UNDER_CE - /* Old Windows CE versions do not support SO_ERROR */ - if(WSAENOPROTOOPT == err) { - SET_SOCKERRNO(0); - err = 0; - } -#endif #if defined(EBADIOCTL) && defined(__minix) /* Minix 3.1.x does not support getsockopt on UDP sockets */ if(EBADIOCTL == err) { @@ -921,7 +892,7 @@ static CURLcode socket_connect_result(struct Curl_easy *data, } struct cf_socket_ctx { - int transport; + uint8_t transport; struct Curl_sockaddr_ex addr; /* address to connect to */ curl_socket_t sock; /* current attempt socket */ struct ip_quadruple ip; /* The IP quadruple 2x(addr+port) */ @@ -937,7 +908,7 @@ struct cf_socket_ctx { int wblock_percent; /* percent of writes doing EAGAIN */ int wpartial_percent; /* percent of bytes written in send */ int rblock_percent; /* percent of reads doing EAGAIN */ - size_t recv_max; /* max enforced read size */ + size_t recv_max; /* max enforced read size */ #endif BIT(got_first_byte); /* if first byte was received */ BIT(listening); /* socket is listening */ @@ -948,7 +919,7 @@ struct cf_socket_ctx { static CURLcode cf_socket_ctx_init(struct cf_socket_ctx *ctx, const struct Curl_addrinfo *ai, - int transport) + uint8_t transport) { CURLcode result; @@ -1038,14 +1009,16 @@ static void cf_socket_destroy(struct Curl_cfilter *cf, struct Curl_easy *data) cf_socket_close(cf, data); CURL_TRC_CF(data, cf, "destroy"); - free(ctx); + curlx_free(ctx); cf->ctx = NULL; } -static CURLcode set_local_ip(struct Curl_cfilter *cf, - struct Curl_easy *data) +static void set_local_ip(struct Curl_cfilter *cf, + struct Curl_easy *data) { struct cf_socket_ctx *ctx = cf->ctx; + ctx->ip.local_ip[0] = 0; + ctx->ip.local_port = 0; #ifdef HAVE_GETSOCKNAME if((ctx->sock != CURL_SOCKET_BAD) && @@ -1057,25 +1030,20 @@ static CURLcode set_local_ip(struct Curl_cfilter *cf, curl_socklen_t slen = sizeof(struct Curl_sockaddr_storage); memset(&ssloc, 0, sizeof(ssloc)); - if(getsockname(ctx->sock, (struct sockaddr*) &ssloc, &slen)) { + if(getsockname(ctx->sock, (struct sockaddr *)&ssloc, &slen)) { int error = SOCKERRNO; - failf(data, "getsockname() failed with errno %d: %s", + infof(data, "getsockname() failed with errno %d: %s", error, curlx_strerror(error, buffer, sizeof(buffer))); - return CURLE_FAILED_INIT; } - if(!Curl_addr2string((struct sockaddr*)&ssloc, slen, - ctx->ip.local_ip, &ctx->ip.local_port)) { - failf(data, "ssloc inet_ntop() failed with errno %d: %s", + else if(!Curl_addr2string((struct sockaddr *)&ssloc, slen, + ctx->ip.local_ip, &ctx->ip.local_port)) { + infof(data, "ssloc inet_ntop() failed with errno %d: %s", errno, curlx_strerror(errno, buffer, sizeof(buffer))); - return CURLE_FAILED_INIT; } } #else (void)data; - ctx->ip.local_ip[0] = 0; - ctx->ip.local_port = -1; #endif - return CURLE_OK; } static CURLcode set_remote_ip(struct Curl_cfilter *cf, @@ -1084,6 +1052,7 @@ static CURLcode set_remote_ip(struct Curl_cfilter *cf, struct cf_socket_ctx *ctx = cf->ctx; /* store remote address and port used in this connection attempt */ + ctx->ip.transport = ctx->transport; if(!Curl_addr2string(&ctx->addr.curl_sa_addr, (curl_socklen_t)ctx->addr.addrlen, ctx->ip.remote_ip, &ctx->ip.remote_port)) { @@ -1109,7 +1078,7 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf, (void)data; DEBUGASSERT(ctx->sock == CURL_SOCKET_BAD); - ctx->started_at = curlx_now(); + ctx->started_at = *Curl_pgrs_now(data); #ifdef SOCK_NONBLOCK /* Do not tuck SOCK_NONBLOCK into socktype when opensocket callback is set * because we would not know how socketype is about to be used in the @@ -1133,7 +1102,18 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf, #ifdef USE_IPV6 if(ctx->addr.family == AF_INET6) { - set_ipv6_v6only(ctx->sock, 0); +#ifdef USE_WINSOCK + /* Turn on support for IPv4-mapped IPv6 addresses. + * Linux kernel, NetBSD, FreeBSD, Darwin, lwIP: default is off; + * Windows Vista and later: default is on; + * DragonFly BSD: acts like off, and dummy setting; + * OpenBSD and earlier Windows: unsupported. + * Linux: controlled by /proc/sys/net/ipv6/bindv6only. + */ + int on = 0; + (void)setsockopt(ctx->sock, IPPROTO_IPV6, IPV6_V6ONLY, + (void *)&on, sizeof(on)); +#endif infof(data, " Trying [%s]:%d...", ctx->ip.remote_ip, ctx->ip.remote_port); } else @@ -1141,22 +1121,22 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf, infof(data, " Trying %s:%d...", ctx->ip.remote_ip, ctx->ip.remote_port); #ifdef USE_IPV6 - is_tcp = (ctx->addr.family == AF_INET - || ctx->addr.family == AF_INET6) && + is_tcp = (ctx->addr.family == AF_INET || + ctx->addr.family == AF_INET6) && ctx->addr.socktype == SOCK_STREAM; #else is_tcp = (ctx->addr.family == AF_INET) && ctx->addr.socktype == SOCK_STREAM; #endif if(is_tcp && data->set.tcp_nodelay) - tcpnodelay(data, ctx->sock); + tcpnodelay(cf, data, ctx->sock); - nosigpipe(data, ctx->sock); + nosigpipe(cf, data, ctx->sock); Curl_sndbuf_init(ctx->sock); if(is_tcp && data->set.tcp_keepalive) - tcpkeepalive(data, ctx->sock); + tcpkeepalive(cf, data, ctx->sock); if(data->set.fsockopt) { /* activate callback for setting socket options */ @@ -1225,7 +1205,7 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf, } else if(isconnected) { set_local_ip(cf, data); - ctx->connected_at = curlx_now(); + ctx->connected_at = *Curl_pgrs_now(data); cf->connected = TRUE; } CURL_TRC_CF(data, cf, "cf_socket_open() -> %d, fd=%" FMT_SOCKET_T, @@ -1270,8 +1250,8 @@ static int do_connect(struct Curl_cfilter *cf, struct Curl_easy *data, #elif defined(TCP_FASTOPEN_CONNECT) /* Linux >= 4.11 */ if(setsockopt(ctx->sock, IPPROTO_TCP, TCP_FASTOPEN_CONNECT, (void *)&optval, sizeof(optval)) < 0) - infof(data, "Failed to enable TCP Fast Open on fd %" FMT_SOCKET_T, - ctx->sock); + CURL_TRC_CF(data, cf, "Failed to enable TCP Fast Open on fd %" + FMT_SOCKET_T, ctx->sock); rc = connect(ctx->sock, &ctx->addr.curl_sa_addr, ctx->addr.addrlen); #elif defined(MSG_FASTOPEN) /* old Linux */ @@ -1338,14 +1318,13 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf, rc = SOCKET_WRITABLE(ctx->sock, 0); if(rc == 0) { /* no connection yet */ - CURL_TRC_CF(data, cf, "not connected yet on fd=%" FMT_SOCKET_T, - ctx->sock); + CURL_TRC_CF(data, cf, "not connected yet on fd=%" FMT_SOCKET_T, ctx->sock); return CURLE_OK; } else if(rc == CURL_CSELECT_OUT || cf->conn->bits.tcp_fastopen) { if(verifyconnect(ctx->sock, &ctx->error)) { /* we are connected with TCP, awesome! */ - ctx->connected_at = curlx_now(); + ctx->connected_at = *Curl_pgrs_now(data); set_local_ip(cf, data); *done = TRUE; cf->connected = TRUE; @@ -1421,33 +1400,34 @@ static CURLcode cf_socket_adjust_pollset(struct Curl_cfilter *cf, #define SIO_IDEAL_SEND_BACKLOG_QUERY 0x4004747B #endif -static void win_update_sndbuf_size(struct cf_socket_ctx *ctx) +static void win_update_sndbuf_size(struct Curl_easy *data, + struct cf_socket_ctx *ctx) { ULONG ideal; DWORD ideallen; - struct curltime n = curlx_now(); - if(curlx_timediff(n, ctx->last_sndbuf_query_at) > 1000) { + if(curlx_ptimediff_ms(Curl_pgrs_now(data), + &ctx->last_sndbuf_query_at) > 1000) { if(!WSAIoctl(ctx->sock, SIO_IDEAL_SEND_BACKLOG_QUERY, 0, 0, - &ideal, sizeof(ideal), &ideallen, 0, 0) && + &ideal, sizeof(ideal), &ideallen, 0, 0) && ideal != ctx->sndbuf_size && !setsockopt(ctx->sock, SOL_SOCKET, SO_SNDBUF, (const char *)&ideal, sizeof(ideal))) { ctx->sndbuf_size = ideal; } - ctx->last_sndbuf_query_at = n; + ctx->last_sndbuf_query_at = *Curl_pgrs_now(data); } } #endif /* USE_WINSOCK */ static CURLcode cf_socket_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, bool eos, + const uint8_t *buf, size_t len, bool eos, size_t *pnwritten) { struct cf_socket_ctx *ctx = cf->ctx; curl_socket_t fdsave; - ssize_t nwritten; + ssize_t rv; size_t orig_len = len; CURLcode result = CURLE_OK; @@ -1461,7 +1441,7 @@ static CURLcode cf_socket_send(struct Curl_cfilter *cf, struct Curl_easy *data, if(ctx->wblock_percent > 0) { unsigned char c = 0; Curl_rand_bytes(data, FALSE, &c, 1); - if(c >= ((100-ctx->wblock_percent)*256/100)) { + if(c >= ((100 - ctx->wblock_percent) * 256 / 100)) { CURL_TRC_CF(data, cf, "send(len=%zu) SIMULATE EWOULDBLOCK", orig_len); cf->conn->sock[cf->sockindex] = fdsave; return CURLE_AGAIN; @@ -1478,15 +1458,15 @@ static CURLcode cf_socket_send(struct Curl_cfilter *cf, struct Curl_easy *data, #if defined(MSG_FASTOPEN) && !defined(TCP_FASTOPEN_CONNECT) /* Linux */ if(cf->conn->bits.tcp_fastopen) { - nwritten = sendto(ctx->sock, buf, len, MSG_FASTOPEN, - &ctx->addr.curl_sa_addr, ctx->addr.addrlen); + rv = sendto(ctx->sock, buf, len, MSG_FASTOPEN, + &ctx->addr.curl_sa_addr, ctx->addr.addrlen); cf->conn->bits.tcp_fastopen = FALSE; } else #endif - nwritten = swrite(ctx->sock, buf, len); + rv = swrite(ctx->sock, buf, len); - if(nwritten < 0) { + if(!curlx_sztouz(rv, pnwritten)) { int sockerr = SOCKERRNO; if( @@ -1513,12 +1493,10 @@ static CURLcode cf_socket_send(struct Curl_cfilter *cf, struct Curl_easy *data, result = CURLE_SEND_ERROR; } } - else - *pnwritten = (size_t)nwritten; #ifdef USE_WINSOCK if(!result) - win_update_sndbuf_size(ctx); + win_update_sndbuf_size(data, ctx); #endif CURL_TRC_CF(data, cf, "send(len=%zu) -> %d, %zu", @@ -1532,7 +1510,7 @@ static CURLcode cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data, { struct cf_socket_ctx *ctx = cf->ctx; CURLcode result = CURLE_OK; - ssize_t nread; + ssize_t rv; *pnread = 0; #ifdef DEBUGBUILD @@ -1540,7 +1518,7 @@ static CURLcode cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data, if(cf->cft != &Curl_cft_udp && ctx->rblock_percent > 0) { unsigned char c = 0; Curl_rand(data, &c, 1); - if(c >= ((100-ctx->rblock_percent)*256/100)) { + if(c >= ((100 - ctx->rblock_percent) * 256 / 100)) { CURL_TRC_CF(data, cf, "recv(len=%zu) SIMULATE EWOULDBLOCK", len); return CURLE_AGAIN; } @@ -1553,9 +1531,9 @@ static CURLcode cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data, } #endif - nread = sread(ctx->sock, buf, len); + rv = sread(ctx->sock, buf, len); - if(nread < 0) { + if(!curlx_sztouz(rv, pnread)) { int sockerr = SOCKERRNO; if( @@ -1581,12 +1559,10 @@ static CURLcode cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data, result = CURLE_RECV_ERROR; } } - else - *pnread = (size_t)nread; CURL_TRC_CF(data, cf, "recv(len=%zu) -> %d, %zu", len, result, *pnread); if(!result && !ctx->got_first_byte) { - ctx->first_byte_at = curlx_now(); + ctx->first_byte_at = *Curl_pgrs_now(data); ctx->got_first_byte = TRUE; } return result; @@ -1656,7 +1632,7 @@ static bool cf_socket_conn_is_alive(struct Curl_cfilter *cf, /* Check with 0 timeout if there are any events pending on the socket */ pfd[0].fd = ctx->sock; - pfd[0].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI; + pfd[0].events = POLLRDNORM | POLLIN | POLLRDBAND | POLLPRI; pfd[0].revents = 0; r = Curl_poll(pfd, 1, 0); @@ -1668,7 +1644,7 @@ static bool cf_socket_conn_is_alive(struct Curl_cfilter *cf, CURL_TRC_CF(data, cf, "is_alive: poll timeout, assume alive"); return TRUE; } - else if(pfd[0].revents & (POLLERR|POLLHUP|POLLPRI|POLLNVAL)) { + else if(pfd[0].revents & (POLLERR | POLLHUP | POLLPRI | POLLNVAL)) { CURL_TRC_CF(data, cf, "is_alive: err/hup/etc events, assume dead"); return FALSE; } @@ -1700,7 +1676,8 @@ static CURLcode cf_socket_query(struct Curl_cfilter *cf, return CURLE_OK; case CF_QUERY_CONNECT_REPLY_MS: if(ctx->got_first_byte) { - timediff_t ms = curlx_timediff(ctx->first_byte_at, ctx->started_at); + timediff_t ms = curlx_ptimediff_ms(&ctx->first_byte_at, + &ctx->started_at); *pres1 = (ms < INT_MAX) ? (int)ms : INT_MAX; } else @@ -1762,7 +1739,7 @@ CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf, struct Curl_easy *data, struct connectdata *conn, const struct Curl_addrinfo *ai, - int transport) + uint8_t transport) { struct cf_socket_ctx *ctx = NULL; struct Curl_cfilter *cf = NULL; @@ -1776,7 +1753,7 @@ CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf, goto out; } - ctx = calloc(1, sizeof(*ctx)); + ctx = curlx_calloc(1, sizeof(*ctx)); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -1798,14 +1775,49 @@ CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf, return result; } +#ifdef __linux__ +static void linux_quic_mtu(struct cf_socket_ctx *ctx) +{ + int val; + switch(ctx->addr.family) { +#ifdef IP_MTU_DISCOVER + case AF_INET: + val = IP_PMTUDISC_DO; + (void)setsockopt(ctx->sock, IPPROTO_IP, IP_MTU_DISCOVER, &val, + sizeof(val)); + break; +#endif +#ifdef IPV6_MTU_DISCOVER + case AF_INET6: + val = IPV6_PMTUDISC_DO; + (void)setsockopt(ctx->sock, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &val, + sizeof(val)); + break; +#endif + } +} +#else +#define linux_quic_mtu(x) +#endif + +#if defined(UDP_GRO) && \ + (defined(HAVE_SENDMMSG) || defined(HAVE_SENDMSG)) && \ + ((defined(USE_NGTCP2) && defined(USE_NGHTTP3)) || defined(USE_QUICHE)) +static void linux_quic_gro(struct cf_socket_ctx *ctx) +{ + int one = 1; + (void)setsockopt(ctx->sock, IPPROTO_UDP, UDP_GRO, &one, + (socklen_t)sizeof(one)); +} +#else +#define linux_quic_gro(x) +#endif + static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf, struct Curl_easy *data) { struct cf_socket_ctx *ctx = cf->ctx; int rc; - int one = 1; - - (void)one; /* QUIC needs a connected socket, nonblocking */ DEBUGASSERT(ctx->sock != CURL_SOCKET_BAD); @@ -1830,33 +1842,8 @@ static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf, * non-blocking socket created by cf_socket_open() to it. Thus, we * do not need to call curlx_nonblock() in cf_udp_setup_quic() anymore. */ -#ifdef __linux__ - switch(ctx->addr.family) { -#ifdef IP_MTU_DISCOVER - case AF_INET: { - int val = IP_PMTUDISC_DO; - (void)setsockopt(ctx->sock, IPPROTO_IP, IP_MTU_DISCOVER, &val, - sizeof(val)); - break; - } -#endif -#ifdef IPV6_MTU_DISCOVER - case AF_INET6: { - int val = IPV6_PMTUDISC_DO; - (void)setsockopt(ctx->sock, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &val, - sizeof(val)); - break; - } -#endif - } - -#if defined(UDP_GRO) && \ - (defined(HAVE_SENDMMSG) || defined(HAVE_SENDMSG)) && \ - ((defined(USE_NGTCP2) && defined(USE_NGHTTP3)) || defined(USE_QUICHE)) - (void)setsockopt(ctx->sock, IPPROTO_UDP, UDP_GRO, &one, - (socklen_t)sizeof(one)); -#endif -#endif + linux_quic_mtu(ctx); + linux_quic_gro(ctx); return CURLE_OK; } @@ -1918,7 +1905,7 @@ CURLcode Curl_cf_udp_create(struct Curl_cfilter **pcf, struct Curl_easy *data, struct connectdata *conn, const struct Curl_addrinfo *ai, - int transport) + uint8_t transport) { struct cf_socket_ctx *ctx = NULL; struct Curl_cfilter *cf = NULL; @@ -1927,7 +1914,7 @@ CURLcode Curl_cf_udp_create(struct Curl_cfilter **pcf, (void)data; (void)conn; DEBUGASSERT(transport == TRNSPRT_UDP || transport == TRNSPRT_QUIC); - ctx = calloc(1, sizeof(*ctx)); + ctx = curlx_calloc(1, sizeof(*ctx)); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -1972,7 +1959,7 @@ CURLcode Curl_cf_unix_create(struct Curl_cfilter **pcf, struct Curl_easy *data, struct connectdata *conn, const struct Curl_addrinfo *ai, - int transport) + uint8_t transport) { struct cf_socket_ctx *ctx = NULL; struct Curl_cfilter *cf = NULL; @@ -1981,7 +1968,7 @@ CURLcode Curl_cf_unix_create(struct Curl_cfilter **pcf, (void)data; (void)conn; DEBUGASSERT(transport == TRNSPRT_UNIX); - ctx = calloc(1, sizeof(*ctx)); + ctx = curlx_calloc(1, sizeof(*ctx)); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -2008,24 +1995,22 @@ static timediff_t cf_tcp_accept_timeleft(struct Curl_cfilter *cf, { struct cf_socket_ctx *ctx = cf->ctx; timediff_t timeout_ms = DEFAULT_ACCEPT_TIMEOUT; - timediff_t other; - struct curltime now; + timediff_t other_ms; #ifndef CURL_DISABLE_FTP if(data->set.accepttimeout > 0) timeout_ms = data->set.accepttimeout; #endif - now = curlx_now(); /* check if the generic timeout possibly is set shorter */ - other = Curl_timeleft(data, &now, FALSE); - if(other && (other < timeout_ms)) - /* note that this also works fine for when other happens to be negative + other_ms = Curl_timeleft_ms(data, FALSE); + if(other_ms && (other_ms < timeout_ms)) + /* note that this also works fine for when other_ms happens to be negative due to it already having elapsed */ - timeout_ms = other; + timeout_ms = other_ms; else { /* subtract elapsed time */ - timeout_ms -= curlx_timediff(now, ctx->started_at); + timeout_ms -= curlx_ptimediff_ms(Curl_pgrs_now(data), &ctx->started_at); if(!timeout_ms) /* avoid returning 0 as that means no timeout! */ timeout_ms = -1; @@ -2046,13 +2031,13 @@ static void cf_tcp_set_accepted_remote_ip(struct Curl_cfilter *cf, ctx->ip.remote_port = 0; plen = sizeof(ssrem); memset(&ssrem, 0, plen); - if(getpeername(ctx->sock, (struct sockaddr*) &ssrem, &plen)) { + if(getpeername(ctx->sock, (struct sockaddr *)&ssrem, &plen)) { int error = SOCKERRNO; failf(data, "getpeername() failed with errno %d: %s", error, curlx_strerror(error, buffer, sizeof(buffer))); return; } - if(!Curl_addr2string((struct sockaddr*)&ssrem, plen, + if(!Curl_addr2string((struct sockaddr *)&ssrem, plen, ctx->ip.remote_ip, &ctx->ip.remote_port)) { failf(data, "ssrem inet_ntop() failed with errno %d: %s", errno, curlx_strerror(errno, buffer, sizeof(buffer))); @@ -2076,7 +2061,7 @@ static CURLcode cf_tcp_accept_connect(struct Curl_cfilter *cf, #else struct sockaddr_in add; #endif - curl_socklen_t size = (curl_socklen_t) sizeof(add); + curl_socklen_t size = (curl_socklen_t)sizeof(add); curl_socket_t s_accepted = CURL_SOCKET_BAD; timediff_t timeout_ms; int socketstate = 0; @@ -2099,8 +2084,7 @@ static CURLcode cf_tcp_accept_connect(struct Curl_cfilter *cf, CURL_TRC_CF(data, cf, "Checking for incoming on fd=%" FMT_SOCKET_T " ip=%s:%d", ctx->sock, ctx->ip.local_ip, ctx->ip.local_port); - socketstate = Curl_socket_check(ctx->sock, CURL_SOCKET_BAD, - CURL_SOCKET_BAD, 0); + socketstate = SOCKET_READABLE(ctx->sock, 0); CURL_TRC_CF(data, cf, "socket_check -> %x", socketstate); switch(socketstate) { case -1: /* error */ @@ -2122,10 +2106,10 @@ static CURLcode cf_tcp_accept_connect(struct Curl_cfilter *cf, size = sizeof(add); #ifdef HAVE_ACCEPT4 - s_accepted = CURL_ACCEPT4(ctx->sock, (struct sockaddr *) &add, &size, + s_accepted = CURL_ACCEPT4(ctx->sock, (struct sockaddr *)&add, &size, SOCK_NONBLOCK | SOCK_CLOEXEC); #else - s_accepted = CURL_ACCEPT(ctx->sock, (struct sockaddr *) &add, &size); + s_accepted = CURL_ACCEPT(ctx->sock, (struct sockaddr *)&add, &size); #endif if(CURL_SOCKET_BAD == s_accepted) { @@ -2133,14 +2117,22 @@ static CURLcode cf_tcp_accept_connect(struct Curl_cfilter *cf, curlx_strerror(SOCKERRNO, errbuf, sizeof(errbuf))); return CURLE_FTP_ACCEPT_FAILED; } -#if !defined(HAVE_ACCEPT4) && defined(HAVE_FCNTL) - if((fcntl(s_accepted, F_SETFD, FD_CLOEXEC) < 0) || - (curlx_nonblock(s_accepted, TRUE) < 0)) { - failf(data, "fcntl set CLOEXEC/NONBLOCK: %s", +#ifndef HAVE_ACCEPT4 +#ifdef HAVE_FCNTL + if(fcntl(s_accepted, F_SETFD, FD_CLOEXEC) < 0) { + failf(data, "fcntl set CLOEXEC: %s", + curlx_strerror(SOCKERRNO, errbuf, sizeof(errbuf))); + Curl_socket_close(data, cf->conn, s_accepted); + return CURLE_FTP_ACCEPT_FAILED; + } +#endif /* HAVE_FCNTL */ + if(curlx_nonblock(s_accepted, TRUE) < 0) { + failf(data, "set socket NONBLOCK: %s", curlx_strerror(SOCKERRNO, errbuf, sizeof(errbuf))); + Curl_socket_close(data, cf->conn, s_accepted); return CURLE_FTP_ACCEPT_FAILED; } -#endif +#endif /* !HAVE_ACCEPT4 */ infof(data, "Connection accepted from server"); /* Replace any filter on SECONDARY with one listening on this socket */ @@ -2153,7 +2145,7 @@ static CURLcode cf_tcp_accept_connect(struct Curl_cfilter *cf, cf_tcp_set_accepted_remote_ip(cf, data); set_local_ip(cf, data); ctx->active = TRUE; - ctx->connected_at = curlx_now(); + ctx->connected_at = *Curl_pgrs_now(data); cf->connected = TRUE; CURL_TRC_CF(data, cf, "accepted_set(sock=%" FMT_SOCKET_T ", remote=%s port=%d)", @@ -2205,7 +2197,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(1, sizeof(*ctx)); + ctx = curlx_calloc(1, sizeof(*ctx)); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -2219,7 +2211,7 @@ CURLcode Curl_conn_tcp_listen_set(struct Curl_easy *data, goto out; Curl_conn_cf_add(data, conn, sockindex, cf); - ctx->started_at = curlx_now(); + ctx->started_at = *Curl_pgrs_now(data); conn->sock[sockindex] = ctx->sock; set_local_ip(cf, data); CURL_TRC_CF(data, cf, "set filter for listen socket fd=%" FMT_SOCKET_T diff --git a/lib/cf-socket.h b/lib/cf-socket.h index e5fc176ee19c..9db492e1c357 100644 --- a/lib/cf-socket.h +++ b/lib/cf-socket.h @@ -25,8 +25,7 @@ ***************************************************************************/ #include "curl_setup.h" -#include "curlx/nonblock.h" /* for curlx_nonblock() */ -#include "sockaddr.h" +#include "sockaddr.h" /* required for Curl_sockaddr_storage */ struct Curl_addrinfo; struct Curl_cfilter; @@ -52,12 +51,12 @@ struct Curl_sockaddr_ex { struct Curl_sockaddr_storage buf; } addr; }; -#define curl_sa_addr addr.sa +#define curl_sa_addr addr.sa #define curl_sa_addrbuf addr.buf /* * Parse interface option, and return the interface name and the host part. -*/ + */ CURLcode Curl_parse_interface(const char *input, char **dev, char **iface, char **host); @@ -71,7 +70,7 @@ CURLcode Curl_parse_interface(const char *input, CURLcode Curl_socket_open(struct Curl_easy *data, const struct Curl_addrinfo *ai, struct Curl_sockaddr_ex *addr, - int transport, + uint8_t transport, curl_socket_t *sockfd); int Curl_socket_close(struct Curl_easy *data, struct connectdata *conn, @@ -103,7 +102,7 @@ CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf, struct Curl_easy *data, struct connectdata *conn, const struct Curl_addrinfo *ai, - int transport); + uint8_t transport); /** * Creates a cfilter that opens a UDP socket to the given address @@ -116,7 +115,7 @@ CURLcode Curl_cf_udp_create(struct Curl_cfilter **pcf, struct Curl_easy *data, struct connectdata *conn, const struct Curl_addrinfo *ai, - int transport); + uint8_t transport); /** * Creates a cfilter that opens a UNIX socket to the given address @@ -129,7 +128,7 @@ CURLcode Curl_cf_unix_create(struct Curl_cfilter **pcf, struct Curl_easy *data, struct connectdata *conn, const struct Curl_addrinfo *ai, - int transport); + uint8_t transport); /** * Creates a cfilter that keeps a listening socket. diff --git a/lib/cfilters.c b/lib/cfilters.c index 2ef5d75d431c..5f3e51111701 100644 --- a/lib/cfilters.c +++ b/lib/cfilters.c @@ -29,18 +29,11 @@ #include "cfilters.h" #include "connect.h" #include "url.h" -#include "sendf.h" -#include "sockaddr.h" /* required for Curl_sockaddr_storage */ -#include "multiif.h" +#include "curl_trc.h" #include "progress.h" #include "select.h" -#include "curlx/warnless.h" #include "curlx/strparse.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - static void cf_cntrl_update_info(struct Curl_easy *data, struct connectdata *conn); @@ -63,8 +56,8 @@ CURLcode Curl_cf_def_shutdown(struct Curl_cfilter *cf, return CURLE_OK; } -static void conn_report_connect_stats(struct Curl_easy *data, - struct connectdata *conn); +static void conn_report_connect_stats(struct Curl_cfilter *cf, + struct Curl_easy *data); CURLcode Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf, struct Curl_easy *data, @@ -85,7 +78,7 @@ bool Curl_cf_def_data_pending(struct Curl_cfilter *cf, } CURLcode Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, bool eos, + const uint8_t *buf, size_t len, bool eos, size_t *pnwritten) { if(cf->next) @@ -143,7 +136,7 @@ void Curl_conn_cf_discard_chain(struct Curl_cfilter **pcf, */ cf->next = NULL; cf->cft->destroy(cf, data); - free(cf); + curlx_free(cf); cf = cfn; } } @@ -173,7 +166,6 @@ CURLcode Curl_conn_shutdown(struct Curl_easy *data, int sockindex, bool *done) struct Curl_cfilter *cf; CURLcode result = CURLE_OK; timediff_t timeout_ms; - struct curltime now; DEBUGASSERT(data->conn); @@ -191,14 +183,13 @@ CURLcode Curl_conn_shutdown(struct Curl_easy *data, int sockindex, bool *done) } *done = FALSE; - now = curlx_now(); if(!Curl_shutdown_started(data, sockindex)) { CURL_TRC_M(data, "shutdown start on%s connection", sockindex ? " secondary" : ""); - Curl_shutdown_start(data, sockindex, 0, &now); + Curl_shutdown_start(data, sockindex, 0); } else { - timeout_ms = Curl_shutdown_timeleft(data->conn, sockindex, &now); + timeout_ms = Curl_shutdown_timeleft(data, data->conn, sockindex); if(timeout_ms < 0) { /* info message, since this might be regarded as acceptable */ infof(data, "shutdown timeout"); @@ -246,7 +237,7 @@ CURLcode Curl_cf_recv(struct Curl_easy *data, int num, char *buf, } CURLcode Curl_cf_send(struct Curl_easy *data, int num, - const void *mem, size_t len, bool eos, + const uint8_t *mem, size_t len, bool eos, size_t *pnwritten) { struct Curl_cfilter *cf; @@ -296,12 +287,11 @@ CURLcode Curl_cf_recv_bufq(struct Curl_cfilter *cf, } static CURLcode cf_bufq_writer(void *writer_ctx, - const unsigned char *buf, size_t buflen, + const uint8_t *buf, size_t buflen, size_t *pnwritten) { struct cf_io_ctx *io = writer_ctx; - return Curl_conn_cf_send(io->cf, io->data, (const char *)buf, - buflen, FALSE, pnwritten); + return Curl_conn_cf_send(io->cf, io->data, buf, buflen, FALSE, pnwritten); } CURLcode Curl_cf_send_bufq(struct Curl_cfilter *cf, @@ -333,7 +323,7 @@ CURLcode Curl_cf_create(struct Curl_cfilter **pcf, CURLcode result = CURLE_OUT_OF_MEMORY; DEBUGASSERT(cft); - cf = calloc(1, sizeof(*cf)); + cf = curlx_calloc(1, sizeof(*cf)); if(!cf) goto out; @@ -422,7 +412,7 @@ void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data) } CURLcode Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, bool eos, + const uint8_t *buf, size_t len, bool eos, size_t *pnwritten) { if(cf) @@ -508,17 +498,16 @@ CURLcode Curl_conn_connect(struct Curl_easy *data, * persist information at the connection. E.g. cf-socket sets the * socket and ip related information. */ cf_cntrl_update_info(data, data->conn); - conn_report_connect_stats(data, data->conn); - data->conn->keepalive = curlx_now(); + conn_report_connect_stats(cf, data); + data->conn->keepalive = *Curl_pgrs_now(data); #ifndef CURL_DISABLE_VERBOSE_STRINGS result = cf_verboseconnect(data, cf); #endif goto out; } else if(result) { - CURL_TRC_CF(data, cf, "Curl_conn_connect(), filter returned %d", - result); - conn_report_connect_stats(data, data->conn); + CURL_TRC_CF(data, cf, "Curl_conn_connect(), filter returned %d", result); + conn_report_connect_stats(cf, data); goto out; } @@ -526,7 +515,7 @@ CURLcode Curl_conn_connect(struct Curl_easy *data, goto out; else { /* check allowed time left */ - const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE); + const timediff_t timeout_ms = Curl_timeleft_ms(data, TRUE); curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data); int rc; @@ -542,8 +531,9 @@ CURLcode Curl_conn_connect(struct Curl_easy *data, Curl_pollfds_reset(&cpfds); /* In general, we want to send after connect, wait on that. */ if(sockfd != CURL_SOCKET_BAD) - Curl_pollset_set_out_only(data, &ps, sockfd); - result = Curl_conn_adjust_pollset(data, data->conn, &ps); + result = Curl_pollset_set_out_only(data, &ps, sockfd); + if(!result) + result = Curl_conn_adjust_pollset(data, data->conn, &ps); if(result) goto out; result = Curl_pollfds_add_ps(&cpfds, &ps); @@ -582,7 +572,11 @@ bool Curl_conn_is_connected(struct connectdata *conn, int sockindex) if(!CONN_SOCK_IDX_VALID(sockindex)) return FALSE; cf = conn->cfilter[sockindex]; - return cf && cf->connected; + if(cf) + return cf->connected; + else if(conn->handler->flags & PROTOPT_NONETWORK) + return TRUE; + return FALSE; } bool Curl_conn_is_ip_connected(struct Curl_easy *data, int sockindex) @@ -657,7 +651,7 @@ bool Curl_conn_is_multiplex(struct connectdata *conn, int sockindex) for(; cf; cf = cf->next) { if(cf->cft->flags & CF_TYPE_MULTIPLEX) return TRUE; - if(cf->cft->flags & (CF_TYPE_IP_CONNECT|CF_TYPE_SSL)) + if(cf->cft->flags & (CF_TYPE_IP_CONNECT | CF_TYPE_SSL)) return FALSE; } return FALSE; @@ -695,7 +689,7 @@ unsigned char Curl_conn_http_version(struct Curl_easy *data, v = (unsigned char)value; break; } - if(cf->cft->flags & (CF_TYPE_IP_CONNECT|CF_TYPE_SSL)) + if(cf->cft->flags & (CF_TYPE_IP_CONNECT | CF_TYPE_SSL)) break; } return (unsigned char)(result ? 0 : v); @@ -807,9 +801,9 @@ void Curl_conn_get_current_host(struct Curl_easy *data, int sockindex, cf = CONN_SOCK_IDX_VALID(sockindex) ? data->conn->cfilter[sockindex] : NULL; /* Find the "lowest" tunneling proxy filter that has not connected yet. */ while(cf && !cf->connected) { - if((cf->cft->flags & (CF_TYPE_IP_CONNECT|CF_TYPE_PROXY)) == - (CF_TYPE_IP_CONNECT|CF_TYPE_PROXY)) - cf_proxy = cf; + if((cf->cft->flags & (CF_TYPE_IP_CONNECT | CF_TYPE_PROXY)) == + (CF_TYPE_IP_CONNECT | CF_TYPE_PROXY)) + cf_proxy = cf; cf = cf->next; } /* cf_proxy (!= NULL) is not connected yet. It is talking @@ -930,19 +924,6 @@ Curl_conn_get_remote_addr(struct Curl_easy *data, int sockindex) return cf ? cf_get_remote_addr(cf, data) : NULL; } -void Curl_conn_forget_socket(struct Curl_easy *data, int sockindex) -{ - struct connectdata *conn = data->conn; - if(conn && CONN_SOCK_IDX_VALID(sockindex)) { - struct Curl_cfilter *cf = conn->cfilter[sockindex]; - if(cf) - (void)Curl_conn_cf_cntrl(cf, data, TRUE, - CF_CTRL_FORGET_SOCKET, 0, NULL); - fake_sclose(conn->sock[sockindex]); - conn->sock[sockindex] = CURL_SOCKET_BAD; - } -} - static CURLcode cf_cntrl_all(struct connectdata *conn, struct Curl_easy *data, bool ignore_result, @@ -962,8 +943,7 @@ static CURLcode cf_cntrl_all(struct connectdata *conn, CURLcode Curl_conn_ev_data_setup(struct Curl_easy *data) { - return cf_cntrl_all(data->conn, data, FALSE, - CF_CTRL_DATA_SETUP, 0, NULL); + return cf_cntrl_all(data->conn, data, FALSE, CF_CTRL_DATA_SETUP, 0, NULL); } CURLcode Curl_conn_flush(struct Curl_easy *data, int sockindex) @@ -1007,10 +987,9 @@ static void cf_cntrl_update_info(struct Curl_easy *data, /** * Update connection statistics */ -static void conn_report_connect_stats(struct Curl_easy *data, - struct connectdata *conn) +static void conn_report_connect_stats(struct Curl_cfilter *cf, + struct Curl_easy *data) { - struct Curl_cfilter *cf = conn->cfilter[FIRSTSOCKET]; if(cf) { struct curltime connected; struct curltime appconnected; @@ -1118,8 +1097,7 @@ CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex, return CURLE_BAD_FUNCTION_ARGUMENT; #ifdef DEBUGBUILD if(write_len) { - /* Allow debug builds to override this logic to force short sends - */ + /* Allow debug builds to override this logic to force short sends */ const char *p = getenv("CURL_SMALLSENDS"); if(p) { curl_off_t altsize; diff --git a/lib/cfilters.h b/lib/cfilters.h index 2fab300b211a..6834c4133a75 100644 --- a/lib/cfilters.h +++ b/lib/cfilters.h @@ -89,7 +89,7 @@ typedef bool Curl_cft_data_pending(struct Curl_cfilter *cf, typedef CURLcode Curl_cft_send(struct Curl_cfilter *cf, struct Curl_easy *data, /* transfer */ - const void *buf, /* data to write */ + const uint8_t *buf, /* data to write */ size_t len, /* amount to write */ bool eos, /* last chunk */ size_t *pnwritten); /* how much sent */ @@ -116,16 +116,16 @@ typedef CURLcode Curl_cft_conn_keep_alive(struct Curl_cfilter *cf, * "ignored" meaning return values are ignored and the event is distributed * to all filters in the chain. Overall result is always CURLE_OK. */ -/* data event arg1 arg2 return */ -#define CF_CTRL_DATA_SETUP 4 /* 0 NULL first fail */ -/* unused now 5 */ -#define CF_CTRL_DATA_PAUSE 6 /* on/off NULL first fail */ -#define CF_CTRL_DATA_DONE 7 /* premature NULL ignored */ -#define CF_CTRL_DATA_DONE_SEND 8 /* 0 NULL ignored */ +/* data event arg1 arg2 return */ +#define CF_CTRL_DATA_SETUP 4 /* 0 NULL first fail */ +/* unused now 5 */ +#define CF_CTRL_DATA_PAUSE 6 /* on/off NULL first fail */ +#define CF_CTRL_DATA_DONE 7 /* premature NULL ignored */ +#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 */ -#define CF_CTRL_FLUSH (256+2) /* 0 NULL first fail */ +#define CF_CTRL_CONN_INFO_UPDATE (256 + 0) /* 0 NULL ignored */ +#define CF_CTRL_FORGET_SOCKET (256 + 1) /* 0 NULL ignored */ +#define CF_CTRL_FLUSH (256 + 2) /* 0 NULL first fail */ /** * Handle event/control for the filter. @@ -135,7 +135,6 @@ typedef CURLcode Curl_cft_cntrl(struct Curl_cfilter *cf, struct Curl_easy *data, int event, int arg1, void *arg2); - /** * Queries to ask via a `Curl_cft_query *query` method on a cfilter chain. * - MAX_CONCURRENT: the maximum number of parallel transfers the filter @@ -210,21 +209,21 @@ typedef CURLcode Curl_cft_query(struct Curl_cfilter *cf, /* A connection filter type, e.g. specific implementation. */ struct Curl_cftype { - const char *name; /* name of the filter type */ - int flags; /* flags of filter type */ - int log_level; /* log level for such filters */ - Curl_cft_destroy_this *destroy; /* destroy resources of this cf */ - Curl_cft_connect *do_connect; /* establish connection */ - Curl_cft_close *do_close; /* close conn */ - Curl_cft_shutdown *do_shutdown; /* shutdown conn */ + const char *name; /* name of the filter type */ + int flags; /* flags of filter type */ + int log_level; /* log level for such filters */ + Curl_cft_destroy_this *destroy; /* destroy resources of this cf */ + Curl_cft_connect *do_connect; /* establish connection */ + Curl_cft_close *do_close; /* close conn */ + Curl_cft_shutdown *do_shutdown; /* shutdown conn */ 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 */ - Curl_cft_cntrl *cntrl; /* events/control */ - Curl_cft_conn_is_alive *is_alive; /* FALSE if conn is dead, Jim! */ - Curl_cft_conn_keep_alive *keep_alive; /* try to keep it alive */ - Curl_cft_query *query; /* query filter chain */ + 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 */ + Curl_cft_cntrl *cntrl; /* events/control */ + Curl_cft_conn_is_alive *is_alive; /* FALSE if conn is dead, Jim! */ + Curl_cft_conn_keep_alive *keep_alive; /* try to keep it alive */ + Curl_cft_query *query; /* query filter chain */ }; /* A connection filter instance, e.g. registered at a connection */ @@ -250,7 +249,7 @@ CURLcode Curl_cf_def_adjust_pollset(struct Curl_cfilter *cf, bool Curl_cf_def_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data); CURLcode Curl_cf_def_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, bool eos, + const uint8_t *buf, size_t len, bool eos, size_t *pnwritten); CURLcode Curl_cf_def_recv(struct Curl_cfilter *cf, struct Curl_easy *data, char *buf, size_t len, size_t *pnread); @@ -317,13 +316,12 @@ void Curl_conn_cf_discard_all(struct Curl_easy *data, struct connectdata *conn, int sockindex); - CURLcode Curl_conn_cf_connect(struct Curl_cfilter *cf, struct Curl_easy *data, bool *done); void Curl_conn_cf_close(struct Curl_cfilter *cf, struct Curl_easy *data); CURLcode Curl_conn_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, bool eos, + const uint8_t *buf, size_t len, bool eos, size_t *pnwritten); CURLcode Curl_conn_cf_recv(struct Curl_cfilter *cf, struct Curl_easy *data, char *buf, size_t len, size_t *pnread); @@ -426,7 +424,7 @@ const char *Curl_conn_get_alpn_negotiated(struct Curl_easy *data, /** * Close the filter chain at `sockindex` for connection `data->conn`. - * Filters remain in place and may be connected again afterwards. + * Filters remain in place and may be connected again afterwards. */ void Curl_conn_close(struct Curl_easy *data, int sockindex); @@ -508,12 +506,12 @@ CURLcode Curl_cf_recv(struct Curl_easy *data, int sockindex, char *buf, * in `*pnwritten` or on error. */ CURLcode Curl_cf_send(struct Curl_easy *data, int sockindex, - const void *buf, size_t len, bool eos, + const uint8_t *buf, size_t len, bool eos, size_t *pnwritten); /** * Receive bytes from connection filter `cf` into `bufq`. - * Convenience wrappter around `Curl_bufq_sipn()`, + * Convenience wrapper around `Curl_bufq_sipn()`, * so users do not have to implement a callback. */ CURLcode Curl_cf_recv_bufq(struct Curl_cfilter *cf, @@ -622,7 +620,6 @@ CURLcode Curl_conn_send(struct Curl_easy *data, int sockindex, const void *buf, size_t blen, bool eos, size_t *pnwritten); - /** * Types and macros used to keep the current easy handle in filter calls, * allowing for nested invocations. See #10336. @@ -654,7 +651,7 @@ struct cf_call_data { * a member in the cfilter's `ctx`. * * #define CF_CTX_CALL_DATA(cf) -> struct cf_call_data instance -*/ + */ #ifdef DEBUGBUILD @@ -688,7 +685,6 @@ struct cf_call_data { #endif /* !DEBUGBUILD */ -#define CF_DATA_CURRENT(cf) \ - ((cf)? (CF_CTX_CALL_DATA(cf).data) : NULL) +#define CF_DATA_CURRENT(cf) ((cf) ? (CF_CTX_CALL_DATA(cf).data) : NULL) #endif /* HEADER_CURL_CFILTERS_H */ diff --git a/lib/config-os400.h b/lib/config-os400.h index bccdb4a8974d..ec6c002efd78 100644 --- a/lib/config-os400.h +++ b/lib/config-os400.h @@ -38,9 +38,9 @@ /* OS400 supports a 3-argument ASCII version of gethostbyaddr_r(), but its * prototype is incompatible with the "standard" one (1st argument is not * const). However, getaddrinfo() is supported (ASCII version defined as - * a local wrapper in setup-os400.h) in a threadsafe way: we can then + * a local wrapper in setup-os400.h) in a thread-safe way: we can then * configure getaddrinfo() as such and get rid of gethostbyname_r() without - * loss of threadsafeness. */ + * loss of thread-safeness. */ #undef HAVE_GETHOSTBYNAME_R #undef HAVE_GETHOSTBYNAME_R_3 #undef HAVE_GETHOSTBYNAME_R_5 @@ -102,9 +102,15 @@ /* Define if you have GSS API. */ #define HAVE_GSSAPI +/* Define if you have the header file. */ +#define HAVE_GSSAPI_H + /* Define if you have the GNU gssapi libraries */ #undef HAVE_GSSGNU +/* Define if you have the `localtime_r' function. */ +#define HAVE_LOCALTIME_R + /* Define if you have the header file. */ #define HAVE_NETDB_H @@ -129,7 +135,6 @@ /* Define if you have the `socket' function. */ #define HAVE_SOCKET - /* The following define is needed on OS400 to enable strcmpi(), stricmp() and strdup(). */ #define __cplusplus__strings__ diff --git a/lib/config-plan9.h b/lib/config-plan9.h index 68d0cf7f569f..616b8e265846 100644 --- a/lib/config-plan9.h +++ b/lib/config-plan9.h @@ -86,6 +86,7 @@ #define HAVE_LIBGEN_H 1 #define HAVE_LIBZ 1 #define HAVE_LOCALE_H 1 +#define HAVE_LOCALTIME_R 1 #define HAVE_LONGLONG 1 #define HAVE_NETDB_H 1 #define HAVE_NETINET_IN_H 1 diff --git a/lib/config-win32.h b/lib/config-win32.h index 408606d61179..002782c6ea9e 100644 --- a/lib/config-win32.h +++ b/lib/config-win32.h @@ -28,8 +28,6 @@ /* Hand crafted config file for Windows */ /* ================================================================ */ -#ifndef UNDER_CE - /* Define some minimum and default build targets for Visual Studio */ #ifdef _MSC_VER /* VS2012 default target settings and minimum build target check. */ @@ -58,63 +56,45 @@ # error VS2012 does not support build targets prior to Windows Vista # endif # endif - /* Default target settings and minimum build target check for - VS2008 and VS2010 */ + /* VS2010 default target settings and minimum build target check. */ # else -# define VS2008_MIN_TARGET 0x0501 /* XP */ - /* VS2008 default build target is Windows Vista (0x0600). + /* VS2010 default build target is Windows 7 (0x0601). We override default target to be Windows XP. */ -# define VS2008_DEF_TARGET 0x0501 /* XP */ +# define VS2010_MIN_TARGET 0x0501 /* XP */ +# define VS2010_DEF_TARGET 0x0501 /* XP */ # ifndef _WIN32_WINNT -# define _WIN32_WINNT VS2008_DEF_TARGET +# define _WIN32_WINNT VS2010_DEF_TARGET # endif # ifndef WINVER -# define WINVER VS2008_DEF_TARGET +# define WINVER VS2010_DEF_TARGET # endif -# if (_WIN32_WINNT < VS2008_MIN_TARGET) || (WINVER < VS2008_MIN_TARGET) -# error VS2008 does not support build targets prior to Windows XP +# if (_WIN32_WINNT < VS2010_MIN_TARGET) || (WINVER < VS2010_MIN_TARGET) +# error VS2010 does not support build targets prior to Windows XP # endif # endif #endif /* _MSC_VER */ -#endif /* UNDER_CE */ - /* ---------------------------------------------------------------- */ /* HEADER FILES */ /* ---------------------------------------------------------------- */ -/* Define if you have the header file. */ -/* #define HAVE_ARPA_INET_H 1 */ - -#ifndef UNDER_CE - /* Define if you have the header file. */ -#define HAVE_FCNTL_H 1 /* exists on __MINGW32CE__ */ +#define HAVE_FCNTL_H 1 /* Define if you have the header file. */ -#define HAVE_IO_H 1 /* exists on __MINGW32CE__ */ +#define HAVE_IO_H 1 /* Define if you have the header file. */ #define HAVE_LOCALE_H 1 -#endif - -/* Define if you have the header file. */ -/* #define HAVE_NETDB_H 1 */ - -/* Define if you have the header file. */ -/* #define HAVE_NETINET_IN_H 1 */ - /* Define to 1 if you have the header file. */ -#ifndef UNDER_CE #if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || defined(__MINGW32__) -#define HAVE_STDBOOL_H 1 /* exists on __MINGW32CE__ */ -#endif +#define HAVE_STDBOOL_H 1 #endif /* Define to 1 if you have the header file. */ -#if (defined(_MSC_VER) && (_MSC_VER >= 1600)) || defined(__MINGW32__) +#if defined(_MSC_VER) || defined(__MINGW32__) #define HAVE_STDINT_H 1 #endif @@ -123,24 +103,12 @@ #define HAVE_SYS_PARAM_H 1 #endif -/* Define if you have the header file. */ -/* #define HAVE_SYS_SELECT_H 1 */ - -/* Define if you have the header file. */ -/* #define HAVE_SYS_SOCKIO_H 1 */ - /* Define if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define if you have the header file. */ #define HAVE_SYS_UTIME_H 1 -/* Define if you have the header file. */ -/* #define HAVE_TERMIO_H 1 */ - -/* Define if you have the header file. */ -/* #define HAVE_TERMIOS_H 1 */ - /* Define if you have the header file. */ #ifdef __MINGW32__ #define HAVE_UNISTD_H 1 @@ -159,10 +127,8 @@ #define STDC_HEADERS 1 /* Define to 1 if bool is an available type. */ -#ifndef UNDER_CE #if (defined(_MSC_VER) && (_MSC_VER >= 1800)) || defined(__MINGW32__) -#define HAVE_BOOL_T 1 /* exists on __MINGW32CE__ */ -#endif +#define HAVE_BOOL_T 1 #endif /* ---------------------------------------------------------------- */ @@ -200,7 +166,6 @@ /* Define if you have the select function. */ #define HAVE_SELECT 1 -#ifndef UNDER_CE /* Define if you have the setlocale function. */ #define HAVE_SETLOCALE 1 @@ -209,7 +174,6 @@ /* Define if you have the _setmode function. */ #define HAVE__SETMODE 1 -#endif /* Define if you have the socket function. */ #define HAVE_SOCKET 1 @@ -276,9 +240,7 @@ #endif /* Define to 1 if you have the signal function. */ -#ifndef UNDER_CE #define HAVE_SIGNAL 1 -#endif /* ---------------------------------------------------------------- */ /* TYPEDEF REPLACEMENTS */ @@ -303,9 +265,6 @@ /* Define to the size of `int', as computed by sizeof. */ #define SIZEOF_INT 4 -/* Define to the size of `long long', as computed by sizeof. */ -/* #define SIZEOF_LONG_LONG 8 */ - /* Define to the size of `long', as computed by sizeof. */ #define SIZEOF_LONG 4 @@ -323,15 +282,6 @@ /* COMPILER SPECIFIC */ /* ---------------------------------------------------------------- */ -/* Define to nothing if compiler does not support 'const' qualifier. */ -/* #define const */ - -/* Define to nothing if compiler does not support 'volatile' qualifier. */ -/* #define volatile */ - -/* Windows should not have HAVE_GMTIME_R defined */ -/* #undef HAVE_GMTIME_R */ - /* Define if the compiler supports the 'long long' data type. */ #if defined(_MSC_VER) || defined(__MINGW32__) #define HAVE_LONGLONG 1 @@ -347,11 +297,9 @@ #endif /* Windows XP is required for freeaddrinfo, getaddrinfo */ -#ifndef UNDER_CE #define HAVE_FREEADDRINFO 1 #define HAVE_GETADDRINFO 1 #define HAVE_GETADDRINFO_THREADSAFE 1 -#endif /* ---------------------------------------------------------------- */ /* STRUCT RELATED */ @@ -370,28 +318,19 @@ /* LARGE FILE SUPPORT */ /* ---------------------------------------------------------------- */ -#ifndef UNDER_CE - -#if defined(_MSC_VER) || defined(__MINGW32__) -# define USE_WIN32_LARGE_FILES /* Number of bits in a file offset, on hosts where this is settable. */ -# ifdef __MINGW32__ -# ifndef _FILE_OFFSET_BITS -# define _FILE_OFFSET_BITS 64 -# endif -# endif +#ifdef __MINGW32__ +# undef _FILE_OFFSET_BITS +# define _FILE_OFFSET_BITS 64 #endif /* Define to the size of `off_t', as computed by sizeof. */ -#if defined(__MINGW32__) && \ - defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64) +#ifdef __MINGW32__ # define SIZEOF_OFF_T 8 #else # define SIZEOF_OFF_T 4 #endif -#endif /* UNDER_CE */ - /* ---------------------------------------------------------------- */ /* DNS RESOLVER SPECIALTY */ /* ---------------------------------------------------------------- */ @@ -400,9 +339,6 @@ * Undefine both USE_ARES and USE_THREADS_WIN32 for synchronous DNS. */ -/* Define to enable c-ares asynchronous DNS lookups. */ -/* #define USE_ARES 1 */ - /* Default define to enable threaded asynchronous DNS lookups. */ #if !defined(USE_SYNC_DNS) && !defined(USE_ARES) && \ !defined(USE_THREADS_WIN32) @@ -417,10 +353,7 @@ /* LDAP SUPPORT */ /* ---------------------------------------------------------------- */ -#ifdef CURL_HAS_OPENLDAP_LDAPSDK -#undef USE_WIN32_LDAP -#define HAVE_LDAP_URL_PARSE 1 -#elif !defined(CURL_WINDOWS_UWP) && !defined(UNDER_CE) +#ifndef CURL_WINDOWS_UWP #undef HAVE_LDAP_URL_PARSE #define HAVE_LDAP_SSL 1 #define USE_WIN32_LDAP 1 @@ -432,9 +365,7 @@ #endif /* Define to use Unix sockets. */ -#ifndef UNDER_CE #define USE_UNIX_SOCKETS -#endif /* ---------------------------------------------------------------- */ /* ADDITIONAL DEFINITIONS */ @@ -442,52 +373,19 @@ /* Define cpu-machine-OS */ #ifndef CURL_OS -# ifdef UNDER_CE -# ifdef _M_ARM -# define CURL_OS "arm-pc-win32ce" -# else -# define CURL_OS "i386-pc-win32ce" -# endif -# else /* !UNDER_CE */ -# if defined(_M_IX86) || defined(__i386__) /* x86 (MSVC or gcc) */ -# define CURL_OS "i386-pc-win32" -# elif defined(_M_X64) || defined(__x86_64__) /* x86_64 (VS2005+ or gcc) */ -# define CURL_OS "x86_64-pc-win32" -# elif defined(_M_IA64) || defined(__ia64__) /* Itanium */ -# define CURL_OS "ia64-pc-win32" -# elif defined(_M_ARM_NT) || defined(__arm__) /* ARMv7-Thumb2 */ -# define CURL_OS "thumbv7a-pc-win32" -# elif defined(_M_ARM64) || defined(__aarch64__) /* ARM64 (Windows 10) */ -# define CURL_OS "aarch64-pc-win32" -# else -# define CURL_OS "unknown-pc-win32" -# endif -# endif /* UNDER_CE */ +# if defined(_M_IX86) || defined(__i386__) /* x86 (MSVC or gcc) */ +# define CURL_OS "i386-pc-win32" +# elif defined(_M_X64) || defined(__x86_64__) /* x86_64 (VS2005+ or gcc) */ +# define CURL_OS "x86_64-pc-win32" +# elif defined(_M_IA64) || defined(__ia64__) /* Itanium */ +# define CURL_OS "ia64-pc-win32" +# elif defined(_M_ARM_NT) || defined(__arm__) /* ARMv7-Thumb2 */ +# define CURL_OS "thumbv7a-pc-win32" +# elif defined(_M_ARM64) || defined(__aarch64__) /* ARM64 (Windows 10) */ +# define CURL_OS "aarch64-pc-win32" +# else +# define CURL_OS "unknown-pc-win32" +# endif #endif /* !CURL_OS */ -/* ---------------------------------------------------------------- */ -/* Windows CE */ -/* ---------------------------------------------------------------- */ - -#ifdef UNDER_CE - -#ifndef UNICODE -#define UNICODE -#endif - -#ifndef _UNICODE -#define _UNICODE -#endif - -#define CURL_DISABLE_FILE 1 -#define CURL_DISABLE_TELNET 1 -#define CURL_DISABLE_LDAP 1 - -#ifndef _MSC_VER -/* !checksrc! disable BANNEDFUNC 1 */ -extern int stat(const char *path, struct stat *buffer); -#endif - -#endif /* UNDER_CE */ - #endif /* HEADER_CURL_CONFIG_WIN32_H */ diff --git a/lib/conncache.c b/lib/conncache.c index 67e2a63d8a57..7fccde05e172 100644 --- a/lib/conncache.c +++ b/lib/conncache.c @@ -25,36 +25,26 @@ #include "curl_setup.h" -#include - #include "urldata.h" #include "url.h" #include "cfilters.h" #include "progress.h" #include "multiif.h" -#include "multi_ev.h" -#include "sendf.h" +#include "curl_trc.h" #include "cshutdn.h" #include "conncache.h" -#include "http_negotiate.h" -#include "http_ntlm.h" -#include "share.h" +#include "curl_share.h" #include "sigpipe.h" #include "connect.h" #include "select.h" #include "curlx/strparse.h" -#include "uint-table.h" - -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" #define CPOOL_IS_LOCKED(c) ((c) && (c)->locked) -#define CPOOL_LOCK(c,d) \ +#define CPOOL_LOCK(c, d) \ do { \ - if((c)) { \ + if(c) { \ if(CURL_SHARE_KEEP_CONNECT((c)->share)) \ Curl_share_lock((d), CURL_LOCK_DATA_CONNECT, \ CURL_LOCK_ACCESS_SINGLE); \ @@ -63,9 +53,9 @@ } \ } while(0) -#define CPOOL_UNLOCK(c,d) \ +#define CPOOL_UNLOCK(c,d) \ do { \ - if((c)) { \ + if(c) { \ DEBUGASSERT((c)->locked); \ (c)->locked = FALSE; \ if(CURL_SHARE_KEEP_CONNECT((c)->share)) \ @@ -73,7 +63,6 @@ } \ } while(0) - /* A list of connections to the same destination. */ struct cpool_bundle { struct Curl_llist conns; /* connections in the bundle */ @@ -81,7 +70,6 @@ struct cpool_bundle { char dest[1]; /* destination of bundle, allocated to keep dest_len bytes */ }; - static void cpool_discard_conn(struct cpool *cpool, struct Curl_easy *data, struct connectdata *conn, @@ -92,7 +80,7 @@ static struct cpool_bundle *cpool_bundle_create(const char *dest) struct cpool_bundle *bundle; size_t dest_len = strlen(dest) + 1; - bundle = calloc(1, sizeof(*bundle) + dest_len - 1); + bundle = curlx_calloc(1, sizeof(*bundle) + dest_len - 1); if(!bundle) return NULL; Curl_llist_init(&bundle->conns, NULL); @@ -104,7 +92,7 @@ static struct cpool_bundle *cpool_bundle_create(const char *dest) static void cpool_bundle_destroy(struct cpool_bundle *bundle) { DEBUGASSERT(!Curl_llist_count(&bundle->conns)); - free(bundle); + curlx_free(bundle); } /* Add a connection to a bundle */ @@ -165,7 +153,6 @@ static struct connectdata *cpool_get_first(struct cpool *cpool) return NULL; } - static struct cpool_bundle *cpool_find_bundle(struct cpool *cpool, struct connectdata *conn) { @@ -173,7 +160,6 @@ static struct cpool_bundle *cpool_find_bundle(struct cpool *cpool, conn->destination, strlen(conn->destination) + 1); } - static void cpool_remove_bundle(struct cpool *cpool, struct cpool_bundle *bundle) { @@ -182,7 +168,6 @@ static void cpool_remove_bundle(struct cpool *cpool, Curl_hash_delete(&cpool->dest2bundle, bundle->dest, bundle->dest_len); } - static void cpool_remove_conn(struct cpool *cpool, struct connectdata *conn) { @@ -220,7 +205,6 @@ void Curl_cpool_destroy(struct cpool *cpool) while(conn) { cpool_remove_conn(cpool, conn); sigpipe_apply(cpool->idata, &pipe_st); - connclose(conn, "kill all"); cpool_discard_conn(cpool, cpool->idata, conn, FALSE); conn = cpool_get_first(cpool); } @@ -265,8 +249,8 @@ void Curl_cpool_xfer_init(struct Curl_easy *data) } } -static struct cpool_bundle * -cpool_add_bundle(struct cpool *cpool, struct connectdata *conn) +static struct cpool_bundle *cpool_add_bundle(struct cpool *cpool, + struct connectdata *conn) { struct cpool_bundle *bundle; @@ -283,23 +267,22 @@ cpool_add_bundle(struct cpool *cpool, struct connectdata *conn) } static struct connectdata * -cpool_bundle_get_oldest_idle(struct cpool_bundle *bundle) +cpool_bundle_get_oldest_idle(struct cpool_bundle *bundle, + const struct curltime *pnow) { struct Curl_llist_node *curr; timediff_t highscore = -1; timediff_t score; - struct curltime now; struct connectdata *oldest_idle = NULL; struct connectdata *conn; - now = curlx_now(); curr = Curl_llist_head(&bundle->conns); while(curr) { conn = Curl_node_elem(curr); if(!CONN_INUSE(conn)) { /* Set higher score for the age passed since the connection was used */ - score = curlx_timediff(now, conn->lastused); + score = curlx_ptimediff_ms(pnow, &conn->lastused); if(score > highscore) { highscore = score; @@ -311,18 +294,17 @@ cpool_bundle_get_oldest_idle(struct cpool_bundle *bundle) return oldest_idle; } -static struct connectdata *cpool_get_oldest_idle(struct cpool *cpool) +static struct connectdata *cpool_get_oldest_idle(struct cpool *cpool, + const struct curltime *pnow) { struct Curl_hash_iterator iter; struct Curl_llist_node *curr; struct Curl_hash_element *he; struct connectdata *oldest_idle = NULL; struct cpool_bundle *bundle; - struct curltime now; timediff_t highscore = -1; timediff_t score; - now = curlx_now(); Curl_hash_start_iterate(&cpool->dest2bundle, &iter); for(he = Curl_hash_next_element(&iter); he; @@ -336,7 +318,7 @@ static struct connectdata *cpool_get_oldest_idle(struct cpool *cpool) if(CONN_INUSE(conn) || conn->bits.close || conn->connect_only) continue; /* Set higher score for the age passed since the connection was used */ - score = curlx_timediff(now, conn->lastused); + score = curlx_ptimediff_ms(pnow, &conn->lastused); if(score > highscore) { highscore = score; oldest_idle = conn; @@ -346,7 +328,6 @@ static struct connectdata *cpool_get_oldest_idle(struct cpool *cpool) return oldest_idle; } - int Curl_cpool_check_limits(struct Curl_easy *data, struct connectdata *conn) { @@ -375,7 +356,7 @@ int Curl_cpool_check_limits(struct Curl_easy *data, bundle = cpool_find_bundle(cpool, conn); live = bundle ? Curl_llist_count(&bundle->conns) : 0; shutdowns = Curl_cshutdn_dest_count(data, conn->destination); - while((live + shutdowns) >= dest_limit) { + while((live + shutdowns) >= dest_limit) { if(shutdowns) { /* close one connection in shutdown right away, if we can */ if(!Curl_cshutdn_close_oldest(data, conn->destination)) @@ -387,14 +368,15 @@ int Curl_cpool_check_limits(struct Curl_easy *data, struct connectdata *oldest_idle = NULL; /* The bundle is full. Extract the oldest connection that may * be removed now, if there is one. */ - oldest_idle = cpool_bundle_get_oldest_idle(bundle); + oldest_idle = cpool_bundle_get_oldest_idle(bundle, + Curl_pgrs_now(data)); if(!oldest_idle) break; /* disconnect the old conn and continue */ - CURL_TRC_M(data, "Discarding connection #%" - FMT_OFF_T " from %zu to reach destination " - "limit of %zu", oldest_idle->connection_id, - Curl_llist_count(&bundle->conns), dest_limit); + CURL_TRC_M(data, "Discarding connection #%" FMT_OFF_T + " from %zu to reach destination limit of %zu", + oldest_idle->connection_id, + Curl_llist_count(&bundle->conns), dest_limit); Curl_conn_terminate(cpool->idata, oldest_idle, FALSE); /* in case the bundle was destroyed in disconnect, look it up again */ @@ -418,7 +400,8 @@ int Curl_cpool_check_limits(struct Curl_easy *data, break; } else { - struct connectdata *oldest_idle = cpool_get_oldest_idle(cpool); + struct connectdata *oldest_idle = + cpool_get_oldest_idle(cpool, Curl_pgrs_now(data)); if(!oldest_idle) break; /* disconnect the old conn and continue */ @@ -531,13 +514,23 @@ static bool cpool_foreach(struct Curl_easy *data, bool Curl_cpool_conn_now_idle(struct Curl_easy *data, struct connectdata *conn) { - unsigned int maxconnects = !data->multi->maxconnects ? - (Curl_multi_xfers_running(data->multi) * 4) : data->multi->maxconnects; + unsigned int maxconnects; struct connectdata *oldest_idle = NULL; struct cpool *cpool = cpool_get_instance(data); bool kept = TRUE; - conn->lastused = curlx_now(); /* it was used up until now */ + if(!data) + return kept; + + if(!data->multi->maxconnects) { + unsigned int running = Curl_multi_xfers_running(data->multi); + maxconnects = (running <= UINT_MAX / 4) ? running * 4 : UINT_MAX; + } + else { + maxconnects = data->multi->maxconnects; + } + + conn->lastused = *Curl_pgrs_now(data); /* it was used up until now */ if(cpool && maxconnects) { /* may be called form a callback already under lock */ bool do_lock = !CPOOL_IS_LOCKED(cpool); @@ -547,7 +540,7 @@ bool Curl_cpool_conn_now_idle(struct Curl_easy *data, infof(data, "Connection pool is full, closing the oldest of %zu/%u", cpool->num_conn, maxconnects); - oldest_idle = cpool_get_oldest_idle(cpool); + oldest_idle = cpool_get_oldest_idle(cpool, Curl_pgrs_now(data)); kept = (oldest_idle != conn); if(oldest_idle) { Curl_conn_terminate(data, oldest_idle, FALSE); @@ -619,7 +612,7 @@ static void cpool_discard_conn(struct cpool *cpool, if(CONN_INUSE(conn) && !aborted) { CURL_TRC_M(data, "[CPOOL] not discarding #%" FMT_OFF_T " still in use by %u transfers", conn->connection_id, - CONN_ATTACHED(conn)); + conn->attached_xfers); return; } @@ -663,7 +656,7 @@ void Curl_conn_terminate(struct Curl_easy *data, * are other users of it */ if(CONN_INUSE(conn) && !aborted) { DEBUGASSERT(0); /* does this ever happen? */ - DEBUGF(infof(data, "Curl_disconnect when inuse: %u", CONN_ATTACHED(conn))); + DEBUGF(infof(data, "conn terminate when inuse: %u", conn->attached_xfers)); return; } @@ -699,18 +692,24 @@ void Curl_conn_terminate(struct Curl_easy *data, CPOOL_UNLOCK(cpool, data); } - struct cpool_reaper_ctx { - struct curltime now; + size_t checked; + size_t reaped; }; static int cpool_reap_dead_cb(struct Curl_easy *data, struct connectdata *conn, void *param) { - struct cpool_reaper_ctx *rctx = param; - if((!CONN_INUSE(conn) && conn->bits.no_reuse) || - Curl_conn_seems_dead(conn, data, &rctx->now)) { + struct cpool_reaper_ctx *reaper = param; + bool terminate = !CONN_INUSE(conn) && conn->bits.no_reuse; + + if(!terminate) { + reaper->checked++; + terminate = Curl_conn_seems_dead(conn, data); + } + if(terminate) { /* stop the iteration here, pass back the connection that was pruned */ + reaper->reaped++; Curl_conn_terminate(data, conn, FALSE); return 1; } @@ -727,20 +726,20 @@ static int cpool_reap_dead_cb(struct Curl_easy *data, void Curl_cpool_prune_dead(struct Curl_easy *data) { struct cpool *cpool = cpool_get_instance(data); - struct cpool_reaper_ctx rctx; + struct cpool_reaper_ctx reaper; timediff_t elapsed; if(!cpool) return; - rctx.now = curlx_now(); + memset(&reaper, 0, sizeof(reaper)); CPOOL_LOCK(cpool, data); - elapsed = curlx_timediff(rctx.now, cpool->last_cleanup); + elapsed = curlx_ptimediff_ms(Curl_pgrs_now(data), &cpool->last_cleanup); if(elapsed >= 1000L) { - while(cpool_foreach(data, cpool, &rctx, cpool_reap_dead_cb)) + while(cpool_foreach(data, cpool, &reaper, cpool_reap_dead_cb)) ; - cpool->last_cleanup = rctx.now; + cpool->last_cleanup = *Curl_pgrs_now(data); } CPOOL_UNLOCK(cpool, data); } @@ -749,21 +748,20 @@ static int conn_upkeep(struct Curl_easy *data, struct connectdata *conn, void *param) { - struct curltime *now = param; - Curl_conn_upkeep(data, conn, now); + (void)param; + Curl_conn_upkeep(data, conn); return 0; /* continue iteration */ } -CURLcode Curl_cpool_upkeep(void *data) +CURLcode Curl_cpool_upkeep(struct Curl_easy *data) { struct cpool *cpool = cpool_get_instance(data); - struct curltime now = curlx_now(); if(!cpool) return CURLE_OK; CPOOL_LOCK(cpool, data); - cpool_foreach(data, cpool, &now, conn_upkeep); + cpool_foreach(data, cpool, NULL, conn_upkeep); CPOOL_UNLOCK(cpool, data); return CURLE_OK; } diff --git a/lib/conncache.h b/lib/conncache.h index a5f133344fd4..fabb967bd0a3 100644 --- a/lib/conncache.h +++ b/lib/conncache.h @@ -25,7 +25,6 @@ * ***************************************************************************/ -#include #include "curlx/timeval.h" struct connectdata; @@ -49,7 +48,7 @@ void Curl_conn_terminate(struct Curl_easy *data, bool aborted); struct cpool { - /* the pooled connections, bundled per destination */ + /* the pooled connections, bundled per destination */ struct Curl_hash dest2bundle; size_t num_conn; curl_off_t next_connection_id; @@ -139,7 +138,7 @@ void Curl_cpool_prune_dead(struct Curl_easy *data); /** * Perform upkeep actions on connections in the transfer's pool. */ -CURLcode Curl_cpool_upkeep(void *data); +CURLcode Curl_cpool_upkeep(struct Curl_easy *data); typedef void Curl_cpool_conn_do_cb(struct connectdata *conn, struct Curl_easy *data, @@ -166,5 +165,4 @@ void Curl_cpool_do_locked(struct Curl_easy *data, /* Close all unused connections, prevent reuse of existing ones. */ void Curl_cpool_nw_changed(struct Curl_easy *data); - #endif /* HEADER_CURL_CONNCACHE_H */ diff --git a/lib/connect.c b/lib/connect.c index 5dc4e2fc747b..bb51701d0ce3 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -51,8 +51,7 @@ #endif #include "urldata.h" -#include "sendf.h" -#include "if2ip.h" +#include "curl_trc.h" #include "strerror.h" #include "cfilters.h" #include "connect.h" @@ -60,156 +59,138 @@ #include "cf-https-connect.h" #include "cf-ip-happy.h" #include "cf-socket.h" -#include "select.h" -#include "url.h" /* for Curl_safefree() */ #include "multiif.h" -#include "sockaddr.h" /* required for Curl_sockaddr_storage */ #include "curlx/inet_ntop.h" -#include "curlx/inet_pton.h" +#include "curlx/strparse.h" #include "vtls/vtls.h" /* for vtsl cfilters */ #include "progress.h" -#include "curlx/warnless.h" #include "conncache.h" #include "multihandle.h" -#include "share.h" #include "http_proxy.h" #include "socks.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - #if !defined(CURL_DISABLE_ALTSVC) || defined(USE_HTTPSRR) -enum alpnid Curl_alpn2alpnid(const char *name, size_t len) +enum alpnid Curl_alpn2alpnid(const unsigned char *name, size_t len) { if(len == 2) { - if(curl_strnequal(name, "h1", 2)) + if(!memcmp(name, "h1", 2)) return ALPN_h1; - if(curl_strnequal(name, "h2", 2)) + if(!memcmp(name, "h2", 2)) return ALPN_h2; - if(curl_strnequal(name, "h3", 2)) + if(!memcmp(name, "h3", 2)) return ALPN_h3; } else if(len == 8) { - if(curl_strnequal(name, "http/1.1", 8)) + if(!memcmp(name, "http/1.1", 8)) return ALPN_h1; } return ALPN_none; /* unknown, probably rubbish input */ } +enum alpnid Curl_str2alpnid(const struct Curl_str *cstr) +{ + return Curl_alpn2alpnid((const unsigned char *)curlx_str(cstr), + curlx_strlen(cstr)); +} + #endif /* - * Curl_timeleft() returns the amount of milliseconds left allowed for the + * Curl_timeleft_ms() returns the amount of milliseconds left allowed for the * transfer/connection. If the value is 0, there is no timeout (ie there is * infinite time left). If the value is negative, the timeout time has already * elapsed. * @param data the transfer to check on - * @param nowp timestamp to use for calculation, NULL to use curlx_now() * @param duringconnect TRUE iff connect timeout is also taken into account. * @unittest: 1303 */ -timediff_t Curl_timeleft(struct Curl_easy *data, - struct curltime *nowp, - bool duringconnect) +timediff_t Curl_timeleft_now_ms(struct Curl_easy *data, + const struct curltime *pnow, + bool duringconnect) { timediff_t timeleft_ms = 0; timediff_t ctimeleft_ms = 0; - struct curltime now; + timediff_t ctimeout_ms; /* The duration of a connect and the total transfer are calculated from two different time-stamps. It can end up with the total timeout being reached 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 && !duringconnect) + if((!data->set.timeout || data->set.connect_only) && !duringconnect) return 0; /* no timeout in place or checked, return "no limit" */ - if(!nowp) { - now = curlx_now(); - nowp = &now; - } - - if(data->set.timeout > 0) { + if(data->set.timeout) { timeleft_ms = data->set.timeout - - curlx_timediff(*nowp, data->progress.t_startop); + curlx_ptimediff_ms(pnow, &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(duringconnect) { - timediff_t ctimeout_ms = (data->set.connecttimeout > 0) ? - data->set.connecttimeout : DEFAULT_CONNECT_TIMEOUT; - ctimeleft_ms = ctimeout_ms - - curlx_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(!duringconnect) + return timeleft_ms; /* no connect check, this is it */ + ctimeout_ms = (data->set.connecttimeout > 0) ? + data->set.connecttimeout : DEFAULT_CONNECT_TIMEOUT; + ctimeleft_ms = ctimeout_ms - + curlx_ptimediff_ms(pnow, &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 */ + /* return minimal time left or max amount already expired */ return (ctimeleft_ms < timeleft_ms) ? ctimeleft_ms : timeleft_ms; } +timediff_t Curl_timeleft_ms(struct Curl_easy *data, + bool duringconnect) +{ + return Curl_timeleft_now_ms(data, Curl_pgrs_now(data), duringconnect); +} + void Curl_shutdown_start(struct Curl_easy *data, int sockindex, - int timeout_ms, struct curltime *nowp) + int timeout_ms) { - struct curltime now; struct connectdata *conn = data->conn; DEBUGASSERT(conn); - if(!nowp) { - now = curlx_now(); - nowp = &now; - } - conn->shutdown.start[sockindex] = *nowp; + conn->shutdown.start[sockindex] = *Curl_pgrs_now(data); conn->shutdown.timeout_ms = (timeout_ms > 0) ? (timediff_t)timeout_ms : ((data->set.shutdowntimeout > 0) ? data->set.shutdowntimeout : DEFAULT_SHUTDOWN_TIMEOUT_MS); /* Set a timer, unless we operate on the admin handle */ if(data->mid) - Curl_expire_ex(data, nowp, conn->shutdown.timeout_ms, - EXPIRE_SHUTDOWN); + Curl_expire_ex(data, conn->shutdown.timeout_ms, EXPIRE_SHUTDOWN); } -timediff_t Curl_shutdown_timeleft(struct connectdata *conn, int sockindex, - struct curltime *nowp) +timediff_t Curl_shutdown_timeleft(struct Curl_easy *data, + struct connectdata *conn, + int sockindex) { - struct curltime now; timediff_t left_ms; if(!conn->shutdown.start[sockindex].tv_sec || (conn->shutdown.timeout_ms <= 0)) return 0; /* not started or no limits */ - if(!nowp) { - now = curlx_now(); - nowp = &now; - } left_ms = conn->shutdown.timeout_ms - - curlx_timediff(*nowp, conn->shutdown.start[sockindex]); + curlx_ptimediff_ms(Curl_pgrs_now(data), + &conn->shutdown.start[sockindex]); return left_ms ? left_ms : -1; } -timediff_t Curl_conn_shutdown_timeleft(struct connectdata *conn, - struct curltime *nowp) +timediff_t Curl_conn_shutdown_timeleft(struct Curl_easy *data, + struct connectdata *conn) { timediff_t left_ms = 0, ms; - struct curltime now; int i; for(i = 0; conn->shutdown.timeout_ms && (i < 2); ++i) { if(!conn->shutdown.start[i].tv_sec) continue; - if(!nowp) { - now = curlx_now(); - nowp = &now; - } - ms = Curl_shutdown_timeleft(conn, i, nowp); + ms = Curl_shutdown_timeleft(data, conn, i); if(ms && (!left_ms || ms < left_ms)) left_ms = ms; } @@ -231,56 +212,53 @@ bool Curl_shutdown_started(struct Curl_easy *data, int sockindex) /* retrieves ip address and port from a sockaddr structure. note it calls curlx_inet_ntop which sets errno on fail, not SOCKERRNO. */ bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen, - char *addr, int *port) + char *addr, uint16_t *port) { struct sockaddr_in *si = NULL; #ifdef USE_IPV6 struct sockaddr_in6 *si6 = NULL; #endif -#if (defined(HAVE_SYS_UN_H) || defined(WIN32_SOCKADDR_UN)) && defined(AF_UNIX) +#ifdef USE_UNIX_SOCKETS struct sockaddr_un *su = NULL; #else (void)salen; #endif switch(sa->sa_family) { - case AF_INET: - si = (struct sockaddr_in *)(void *) sa; - if(curlx_inet_ntop(sa->sa_family, &si->sin_addr, addr, MAX_IPADR_LEN)) { - unsigned short us_port = ntohs(si->sin_port); - *port = us_port; - return TRUE; - } - break; + case AF_INET: + si = (struct sockaddr_in *)(void *)sa; + if(curlx_inet_ntop(sa->sa_family, &si->sin_addr, addr, MAX_IPADR_LEN)) { + *port = ntohs(si->sin_port); + return TRUE; + } + break; #ifdef USE_IPV6 - case AF_INET6: - si6 = (struct sockaddr_in6 *)(void *) sa; - if(curlx_inet_ntop(sa->sa_family, &si6->sin6_addr, addr, - MAX_IPADR_LEN)) { - unsigned short us_port = ntohs(si6->sin6_port); - *port = us_port; - return TRUE; - } - break; -#endif -#if (defined(HAVE_SYS_UN_H) || defined(WIN32_SOCKADDR_UN)) && defined(AF_UNIX) - case AF_UNIX: - if(salen > (curl_socklen_t)sizeof(CURL_SA_FAMILY_T)) { - su = (struct sockaddr_un*)sa; - curl_msnprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path); - } - else - addr[0] = 0; /* socket with no name */ - *port = 0; + case AF_INET6: + si6 = (struct sockaddr_in6 *)(void *)sa; + if(curlx_inet_ntop(sa->sa_family, &si6->sin6_addr, addr, MAX_IPADR_LEN)) { + *port = ntohs(si6->sin6_port); return TRUE; + } + break; #endif - default: - break; +#ifdef USE_UNIX_SOCKETS + case AF_UNIX: + if(salen > (curl_socklen_t)sizeof(CURL_SA_FAMILY_T)) { + su = (struct sockaddr_un *)sa; + curl_msnprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path); + } + else + addr[0] = 0; /* socket with no name */ + *port = 0; + return TRUE; +#endif + default: + break; } addr[0] = '\0'; *port = 0; - CURL_SETERRNO(SOCKEAFNOSUPPORT); + errno = SOCKEAFNOSUPPORT; return FALSE; } @@ -337,7 +315,7 @@ void Curl_conncontrol(struct connectdata *conn, #endif is_multiplex = Curl_conn_is_multiplex(conn, FIRSTSOCKET); closeit = (ctrl == CONNCTRL_CONNECTION) || - ((ctrl == CONNCTRL_STREAM) && !is_multiplex); + ((ctrl == CONNCTRL_STREAM) && !is_multiplex); if((ctrl == CONNCTRL_STREAM) && is_multiplex) ; /* stream signal on multiplex conn never affects close state */ else if((bit)closeit != conn->bits.close) { @@ -359,7 +337,7 @@ typedef enum { struct cf_setup_ctx { cf_setup_state state; int ssl_mode; - int transport; + uint8_t transport; }; static CURLcode cf_setup_connect(struct Curl_cfilter *cf, @@ -408,8 +386,8 @@ static CURLcode cf_setup_connect(struct Curl_cfilter *cf, if(ctx->state < CF_SETUP_CNNCT_HTTP_PROXY && cf->conn->bits.httpproxy) { #ifdef USE_SSL - if(IS_HTTPS_PROXY(cf->conn->http_proxy.proxytype) - && !Curl_conn_is_ssl(cf->conn, cf->sockindex)) { + if(IS_HTTPS_PROXY(cf->conn->http_proxy.proxytype) && + !Curl_conn_is_ssl(cf->conn, cf->sockindex)) { result = Curl_cf_ssl_proxy_insert_after(cf, data); if(result) return result; @@ -449,9 +427,9 @@ static CURLcode cf_setup_connect(struct Curl_cfilter *cf, if(ctx->state < CF_SETUP_CNNCT_SSL) { #ifdef USE_SSL - if((ctx->ssl_mode == CURL_CF_SSL_ENABLE - || (ctx->ssl_mode != CURL_CF_SSL_DISABLE - && cf->conn->handler->flags & PROTOPT_SSL)) /* we want SSL */ + if((ctx->ssl_mode == CURL_CF_SSL_ENABLE || + (ctx->ssl_mode != CURL_CF_SSL_DISABLE && + cf->conn->handler->flags & PROTOPT_SSL)) /* we want SSL */ && !Curl_conn_is_ssl(cf->conn, cf->sockindex)) { /* it is missing */ result = Curl_cf_ssl_insert_after(cf, data); if(result) @@ -493,7 +471,6 @@ static void cf_setup_destroy(struct Curl_cfilter *cf, struct Curl_easy *data) Curl_safefree(ctx); } - struct Curl_cftype Curl_cft_setup = { "SETUP", 0, @@ -514,7 +491,7 @@ struct Curl_cftype Curl_cft_setup = { static CURLcode cf_setup_create(struct Curl_cfilter **pcf, struct Curl_easy *data, - int transport, + uint8_t transport, int ssl_mode) { struct Curl_cfilter *cf = NULL; @@ -522,7 +499,7 @@ static CURLcode cf_setup_create(struct Curl_cfilter **pcf, CURLcode result = CURLE_OK; (void)data; - ctx = calloc(1, sizeof(*ctx)); + ctx = curlx_calloc(1, sizeof(*ctx)); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -539,7 +516,7 @@ static CURLcode cf_setup_create(struct Curl_cfilter **pcf, out: *pcf = result ? NULL : cf; if(ctx) { - free(ctx); + curlx_free(ctx); } return result; } @@ -547,7 +524,7 @@ static CURLcode cf_setup_create(struct Curl_cfilter **pcf, static CURLcode cf_setup_add(struct Curl_easy *data, struct connectdata *conn, int sockindex, - int transport, + uint8_t transport, int ssl_mode) { struct Curl_cfilter *cf; @@ -564,7 +541,7 @@ static CURLcode cf_setup_add(struct Curl_easy *data, CURLcode Curl_cf_setup_insert_after(struct Curl_cfilter *cf_at, struct Curl_easy *data, - int transport, + uint8_t transport, int ssl_mode) { struct Curl_cfilter *cf; diff --git a/lib/connect.h b/lib/connect.h index cb185b2c571b..01e9dfc02910 100644 --- a/lib/connect.h +++ b/lib/connect.h @@ -25,37 +25,40 @@ ***************************************************************************/ #include "curl_setup.h" -#include "curlx/nonblock.h" /* for curlx_nonblock() */ -#include "sockaddr.h" #include "curlx/timeval.h" struct Curl_dns_entry; struct ip_quadruple; +struct Curl_str; -enum alpnid Curl_alpn2alpnid(const char *name, size_t len); +enum alpnid Curl_alpn2alpnid(const unsigned char *name, size_t len); +enum alpnid Curl_str2alpnid(const struct Curl_str *str); /* generic function that returns how much time there is left to run, according to the timeouts set */ -timediff_t Curl_timeleft(struct Curl_easy *data, - struct curltime *nowp, - bool duringconnect); +timediff_t Curl_timeleft_ms(struct Curl_easy *data, + bool duringconnect); +timediff_t Curl_timeleft_now_ms(struct Curl_easy *data, + const struct curltime *pnow, + bool duringconnect); #define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */ #define DEFAULT_SHUTDOWN_TIMEOUT_MS (2 * 1000) void Curl_shutdown_start(struct Curl_easy *data, int sockindex, - int timeout_ms, struct curltime *nowp); + int timeout_ms); /* return how much time there is left to shutdown the connection at * sockindex. Returns 0 if there is no limit or shutdown has not started. */ -timediff_t Curl_shutdown_timeleft(struct connectdata *conn, int sockindex, - struct curltime *nowp); +timediff_t Curl_shutdown_timeleft(struct Curl_easy *data, + struct connectdata *conn, + int sockindex); /* return how much time there is left to shutdown the connection. * Returns 0 if there is no limit or shutdown has not started. */ -timediff_t Curl_conn_shutdown_timeleft(struct connectdata *conn, - struct curltime *nowp); +timediff_t Curl_conn_shutdown_timeleft(struct Curl_easy *data, + struct connectdata *conn); void Curl_shutdown_clear(struct Curl_easy *data, int sockindex); @@ -72,7 +75,7 @@ curl_socket_t Curl_getconnectinfo(struct Curl_easy *data, struct connectdata **connp); bool Curl_addr2string(struct sockaddr *sa, curl_socklen_t salen, - char *addr, int *port); + char *addr, uint16_t *port); /* * Curl_conncontrol() marks the end of a connection/stream. The 'closeit' @@ -98,18 +101,18 @@ void Curl_conncontrol(struct connectdata *conn, ); #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) -#define streamclose(x,y) Curl_conncontrol(x, CONNCTRL_STREAM, y) -#define connclose(x,y) Curl_conncontrol(x, CONNCTRL_CONNECTION, y) -#define connkeep(x,y) Curl_conncontrol(x, CONNCTRL_KEEP, y) +#define streamclose(x, y) Curl_conncontrol(x, CONNCTRL_STREAM, y) +#define connclose(x, y) Curl_conncontrol(x, CONNCTRL_CONNECTION, y) +#define connkeep(x, y) Curl_conncontrol(x, CONNCTRL_KEEP, y) #else /* if !DEBUGBUILD || CURL_DISABLE_VERBOSE_STRINGS */ -#define streamclose(x,y) Curl_conncontrol(x, CONNCTRL_STREAM) -#define connclose(x,y) Curl_conncontrol(x, CONNCTRL_CONNECTION) -#define connkeep(x,y) Curl_conncontrol(x, CONNCTRL_KEEP) +#define streamclose(x, y) Curl_conncontrol(x, CONNCTRL_STREAM) +#define connclose(x, y) Curl_conncontrol(x, CONNCTRL_CONNECTION) +#define connkeep(x, y) Curl_conncontrol(x, CONNCTRL_KEEP) #endif CURLcode Curl_cf_setup_insert_after(struct Curl_cfilter *cf_at, struct Curl_easy *data, - int transport, + uint8_t transport, int ssl_mode); /** diff --git a/lib/content_encoding.c b/lib/content_encoding.c index 28cccacdb647..d878bb49ac27 100644 --- a/lib/content_encoding.c +++ b/lib/content_encoding.c @@ -25,8 +25,7 @@ #include "curl_setup.h" #include "urldata.h" -#include -#include +#include "curlx/dynbuf.h" #ifdef HAVE_LIBZ #include @@ -49,13 +48,9 @@ #endif #include "sendf.h" +#include "curl_trc.h" #include "http.h" #include "content_encoding.h" -#include "strdup.h" - -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" #define CONTENT_ENCODING_DEFAULT "identity" @@ -91,24 +86,20 @@ struct zlib_writer { z_stream z; /* State structure for zlib. */ }; - -static voidpf -zalloc_cb(voidpf opaque, unsigned int items, unsigned int size) +static voidpf zalloc_cb(voidpf opaque, unsigned int items, unsigned int size) { (void)opaque; - /* not a typo, keep it calloc() */ - return (voidpf) calloc(items, size); + /* not a typo, keep it curlx_calloc() */ + return (voidpf)curlx_calloc(items, size); } -static void -zfree_cb(voidpf opaque, voidpf ptr) +static void zfree_cb(voidpf opaque, voidpf ptr) { (void)opaque; - free(ptr); + curlx_free(ptr); } -static CURLcode -process_zlib_error(struct Curl_easy *data, z_stream *z) +static CURLcode process_zlib_error(struct Curl_easy *data, z_stream *z) { if(z->msg) failf(data, "Error while processing content unencoding: %s", @@ -120,9 +111,8 @@ process_zlib_error(struct Curl_easy *data, z_stream *z) return CURLE_BAD_CONTENT_ENCODING; } -static CURLcode -exit_zlib(struct Curl_easy *data, - z_stream *z, zlibInitState *zlib_init, CURLcode result) +static CURLcode exit_zlib(struct Curl_easy *data, z_stream *z, + zlibInitState *zlib_init, CURLcode result) { if(*zlib_init != ZLIB_UNINIT) { if(inflateEnd(z) != Z_OK && result == CURLE_OK) @@ -133,8 +123,7 @@ exit_zlib(struct Curl_easy *data, return result; } -static CURLcode process_trailer(struct Curl_easy *data, - struct zlib_writer *zp) +static CURLcode process_trailer(struct Curl_easy *data, struct zlib_writer *zp) { z_stream *z = &zp->z; CURLcode result = CURLE_OK; @@ -161,7 +150,7 @@ static CURLcode inflate_stream(struct Curl_easy *data, struct Curl_cwriter *writer, int type, zlibInitState started) { - struct zlib_writer *zp = (struct zlib_writer *) writer; + struct zlib_writer *zp = (struct zlib_writer *)writer; z_stream *z = &zp->z; /* zlib state structure */ uInt nread = z->avail_in; z_const Bytef *orig_in = z->next_in; @@ -181,7 +170,7 @@ static CURLcode inflate_stream(struct Curl_easy *data, done = TRUE; /* (re)set buffer for decompressed output for every iteration */ - z->next_out = (Bytef *) zp->buffer; + z->next_out = (Bytef *)zp->buffer; z->avail_out = DECOMPRESS_BUFFER_SIZE; status = inflate(z, Z_BLOCK); @@ -242,17 +231,16 @@ static CURLcode inflate_stream(struct Curl_easy *data, return result; } - /* Deflate handler. */ static CURLcode deflate_do_init(struct Curl_easy *data, struct Curl_cwriter *writer) { - struct zlib_writer *zp = (struct zlib_writer *) writer; + struct zlib_writer *zp = (struct zlib_writer *)writer; z_stream *z = &zp->z; /* zlib state structure */ /* Initialize zlib */ - z->zalloc = (alloc_func) zalloc_cb; - z->zfree = (free_func) zfree_cb; + z->zalloc = (alloc_func)zalloc_cb; + z->zfree = (free_func)zfree_cb; if(inflateInit(z) != Z_OK) return process_zlib_error(data, z); @@ -264,7 +252,7 @@ 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; + struct zlib_writer *zp = (struct zlib_writer *)writer; z_stream *z = &zp->z; /* zlib state structure */ if(!(type & CLIENTWRITE_BODY) || !nbytes) @@ -284,7 +272,7 @@ static CURLcode deflate_do_write(struct Curl_easy *data, static void deflate_do_close(struct Curl_easy *data, struct Curl_cwriter *writer) { - struct zlib_writer *zp = (struct zlib_writer *) writer; + struct zlib_writer *zp = (struct zlib_writer *)writer; z_stream *z = &zp->z; /* zlib state structure */ exit_zlib(data, z, &zp->zlib_init, CURLE_OK); @@ -299,17 +287,19 @@ static const struct Curl_cwtype deflate_encoding = { sizeof(struct zlib_writer) }; +/* + * Gzip handler. + */ -/* Gzip handler. */ static CURLcode gzip_do_init(struct Curl_easy *data, struct Curl_cwriter *writer) { - struct zlib_writer *zp = (struct zlib_writer *) writer; + struct zlib_writer *zp = (struct zlib_writer *)writer; z_stream *z = &zp->z; /* zlib state structure */ /* Initialize zlib */ - z->zalloc = (alloc_func) zalloc_cb; - z->zfree = (free_func) zfree_cb; + z->zalloc = (alloc_func)zalloc_cb; + z->zfree = (free_func)zfree_cb; if(inflateInit2(z, MAX_WBITS + 32) != Z_OK) return process_zlib_error(data, z); @@ -322,7 +312,7 @@ 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; + struct zlib_writer *zp = (struct zlib_writer *)writer; z_stream *z = &zp->z; /* zlib state structure */ if(!(type & CLIENTWRITE_BODY) || !nbytes) @@ -343,7 +333,7 @@ static CURLcode gzip_do_write(struct Curl_easy *data, static void gzip_do_close(struct Curl_easy *data, struct Curl_cwriter *writer) { - struct zlib_writer *zp = (struct zlib_writer *) writer; + struct zlib_writer *zp = (struct zlib_writer *)writer; z_stream *z = &zp->z; /* zlib state structure */ exit_zlib(data, z, &zp->zlib_init, CURLE_OK); @@ -385,12 +375,10 @@ static CURLcode brotli_map_error(BrotliDecoderErrorCode be) case BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS: case BROTLI_DECODER_ERROR_FORMAT_PADDING_1: case BROTLI_DECODER_ERROR_FORMAT_PADDING_2: -#ifdef BROTLI_DECODER_ERROR_COMPOUND_DICTIONARY +#ifdef BROTLI_DECODER_ERROR_COMPOUND_DICTIONARY /* brotli v1.1.0+ */ case BROTLI_DECODER_ERROR_COMPOUND_DICTIONARY: #endif -#ifdef BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET case BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET: -#endif case BROTLI_DECODER_ERROR_INVALID_ARGUMENTS: return CURLE_BAD_CONTENT_ENCODING; case BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES: @@ -409,7 +397,7 @@ static CURLcode brotli_map_error(BrotliDecoderErrorCode be) static CURLcode brotli_do_init(struct Curl_easy *data, struct Curl_cwriter *writer) { - struct brotli_writer *bp = (struct brotli_writer *) writer; + struct brotli_writer *bp = (struct brotli_writer *)writer; (void)data; bp->br = BrotliDecoderCreateInstance(NULL, NULL, NULL); @@ -420,8 +408,8 @@ 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; - const uint8_t *src = (const uint8_t *) buf; + struct brotli_writer *bp = (struct brotli_writer *)writer; + const uint8_t *src = (const uint8_t *)buf; uint8_t *dst; size_t dstleft; CURLcode result = CURLE_OK; @@ -435,7 +423,7 @@ static CURLcode brotli_do_write(struct Curl_easy *data, while((nbytes || r == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) && result == CURLE_OK) { - dst = (uint8_t *) bp->buffer; + dst = (uint8_t *)bp->buffer; dstleft = DECOMPRESS_BUFFER_SIZE; r = BrotliDecoderDecompressStream(bp->br, &nbytes, &src, &dstleft, &dst, NULL); @@ -464,7 +452,7 @@ static CURLcode brotli_do_write(struct Curl_easy *data, static void brotli_do_close(struct Curl_easy *data, struct Curl_cwriter *writer) { - struct brotli_writer *bp = (struct brotli_writer *) writer; + struct brotli_writer *bp = (struct brotli_writer *)writer; (void)data; if(bp->br) { @@ -508,7 +496,7 @@ static void Curl_zstd_free(void *opaque, void *address) static CURLcode zstd_do_init(struct Curl_easy *data, struct Curl_cwriter *writer) { - struct zstd_writer *zp = (struct zstd_writer *) writer; + struct zstd_writer *zp = (struct zstd_writer *)writer; (void)data; @@ -530,7 +518,7 @@ static CURLcode zstd_do_write(struct Curl_easy *data, const char *buf, size_t nbytes) { CURLcode result = CURLE_OK; - struct zstd_writer *zp = (struct zstd_writer *) writer; + struct zstd_writer *zp = (struct zstd_writer *)writer; ZSTD_inBuffer in; ZSTD_outBuffer out; size_t errorCode; @@ -567,7 +555,7 @@ static CURLcode zstd_do_write(struct Curl_easy *data, static void zstd_do_close(struct Curl_easy *data, struct Curl_cwriter *writer) { - struct zstd_writer *zp = (struct zstd_writer *) writer; + struct zstd_writer *zp = (struct zstd_writer *)writer; (void)data; if(zp->zds) { @@ -620,41 +608,27 @@ static const struct Curl_cwtype * const transfer_unencoders[] = { NULL }; -/* Provide a list of comma-separated names of supported encodings. -*/ -void Curl_all_content_encodings(char *buf, size_t blen) +/* Return the list of comma-separated names of supported encodings. + */ +char *Curl_get_content_encodings(void) { - size_t len = 0; + struct dynbuf enc; const struct Curl_cwtype * const *cep; - const struct Curl_cwtype *ce; - - DEBUGASSERT(buf); - DEBUGASSERT(blen); - buf[0] = 0; - - for(cep = general_unencoders; *cep; cep++) { - ce = *cep; - if(!curl_strequal(ce->name, CONTENT_ENCODING_DEFAULT)) - len += strlen(ce->name) + 2; - } + CURLcode result = CURLE_OK; + curlx_dyn_init(&enc, 255); - 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(!curl_strequal(ce->name, CONTENT_ENCODING_DEFAULT)) { - strcpy(p, ce->name); - p += strlen(p); - *p++ = ','; - *p++ = ' '; - } + for(cep = general_unencoders; *cep && !result; cep++) { + const struct Curl_cwtype *ce = *cep; + if(!curl_strequal(ce->name, CONTENT_ENCODING_DEFAULT)) { + if(curlx_dyn_len(&enc)) + result = curlx_dyn_addn(&enc, ", ", 2); + if(!result) + result = curlx_dyn_add(&enc, ce->name); } - p[-2] = '\0'; } + if(!result) + return curlx_dyn_ptr(&enc); + return NULL; } /* Deferred error dummy writer. */ @@ -676,12 +650,7 @@ static CURLcode error_do_write(struct Curl_easy *data, if(!(type & CLIENTWRITE_BODY) || !nbytes) return Curl_cwriter_write(data, writer->next, type, buf, nbytes); - else { - char all[256]; - (void)Curl_all_content_encodings(all, sizeof(all)); - failf(data, "Unrecognized content encoding type. " - "libcurl understands %s content encodings.", all); - } + failf(data, "Unrecognized content encoding type"); return CURLE_BAD_CONTENT_ENCODING; } @@ -848,14 +817,9 @@ CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, return CURLE_NOT_BUILT_IN; } -void Curl_all_content_encodings(char *buf, size_t blen) +char *Curl_get_content_encodings(void) { - DEBUGASSERT(buf); - DEBUGASSERT(blen); - if(blen < sizeof(CONTENT_ENCODING_DEFAULT)) - buf[0] = 0; - else - strcpy(buf, CONTENT_ENCODING_DEFAULT); + return curlx_strdup(CONTENT_ENCODING_DEFAULT); } #endif /* CURL_DISABLE_HTTP */ diff --git a/lib/content_encoding.h b/lib/content_encoding.h index 1addf230bbf5..e84a7397614f 100644 --- a/lib/content_encoding.h +++ b/lib/content_encoding.h @@ -27,7 +27,8 @@ struct Curl_cwriter; -void Curl_all_content_encodings(char *buf, size_t blen); +/* returns an allocated string or NULL */ +char *Curl_get_content_encodings(void); CURLcode Curl_build_unencoding_stack(struct Curl_easy *data, const char *enclist, int is_transfer); diff --git a/lib/cookie.c b/lib/cookie.c index 59a841a303c7..cb81c8e6cc43 100644 --- a/lib/cookie.c +++ b/lib/cookie.c @@ -22,53 +22,6 @@ * ***************************************************************************/ -/*** - - -RECEIVING COOKIE INFORMATION -============================ - -Curl_cookie_init() - - Inits a cookie struct to store data in a local file. This is always - called before any cookies are set. - -Curl_cookie_add() - - Adds a cookie to the in-memory cookie jar. - - -SENDING COOKIE INFORMATION -========================== - -Curl_cookie_getlist() - - For a given host and path, return a linked list of cookies that - the client should send to the server if used now. The secure - boolean informs the cookie if a secure connection is achieved or - not. - - It shall only return cookies that have not expired. - -Example set of cookies: - - Set-cookie: PRODUCTINFO=webxpress; domain=.fidelity.com; path=/; secure - Set-cookie: PERSONALIZE=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; - domain=.fidelity.com; path=/ftgw; secure - Set-cookie: FidHist=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; - domain=.fidelity.com; path=/; secure - Set-cookie: FidOrder=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; - domain=.fidelity.com; path=/; secure - Set-cookie: DisPend=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; - domain=.fidelity.com; path=/; secure - Set-cookie: FidDis=none;expires=Monday, 13-Jun-1988 03:04:55 GMT; - domain=.fidelity.com; path=/; secure - Set-cookie: - Session_Key@6791a9e0-901a-11d0-a1c8-9b012c88aa77=none;expires=Monday, - 13-Jun-1988 03:04:55 GMT; domain=.fidelity.com; path=/; secure -****/ - - #include "curl_setup.h" #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) @@ -76,27 +29,21 @@ Example set of cookies: #include "urldata.h" #include "cookie.h" #include "psl.h" -#include "sendf.h" +#include "curl_trc.h" #include "slist.h" -#include "share.h" +#include "curl_share.h" #include "strcase.h" #include "curl_fopen.h" #include "curl_get_line.h" #include "curl_memrchr.h" #include "parsedate.h" -#include "rename.h" #include "strdup.h" #include "llist.h" +#include "bufref.h" #include "curlx/strparse.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - -static void strstore(char **str, const char *newstr, size_t len); - /* number of seconds in 400 days */ -#define COOKIES_MAXAGE (400*24*3600) +#define COOKIES_MAXAGE (400 * 24 * 3600) /* Make sure cookies never expire further away in time than 400 days into the future. (from RFC6265bis draft-19) @@ -110,19 +57,19 @@ static void cap_expires(time_t now, struct Cookie *co) timediff_t cap = now + COOKIES_MAXAGE; if(co->expires > cap) { cap += 30; - co->expires = (cap/60)*60; + co->expires = (cap / 60) * 60; } } } -static void freecookie(struct Cookie *co) +static void freecookie(struct Cookie *co, bool maintoo) { - free(co->domain); - free(co->path); - free(co->spath); - free(co->name); - free(co->value); - free(co); + curlx_free(co->domain); + curlx_free(co->path); + curlx_free(co->name); + curlx_free(co->value); + if(maintoo) + curlx_free(co); } static bool cookie_tailmatch(const char *cookie_domain, @@ -135,7 +82,7 @@ static bool cookie_tailmatch(const char *cookie_domain, return FALSE; if(!curl_strnequal(cookie_domain, - hostname + hostname_len-cookie_domain_len, + hostname + hostname_len - cookie_domain_len, cookie_domain_len)) return FALSE; @@ -278,22 +225,21 @@ static size_t cookiehash(const char * const domain) /* * cookie path sanitize */ -static char *sanitize_cookie_path(const char *cookie_path) +static char *sanitize_cookie_path(const char *cookie_path, size_t len) { - size_t len = strlen(cookie_path); - /* some sites send path attribute within '"'. */ - if(cookie_path[0] == '\"') { + if(len && (cookie_path[0] == '\"')) { cookie_path++; len--; + + if(len && (cookie_path[len - 1] == '\"')) + len--; } - if(len && (cookie_path[len - 1] == '\"')) - len--; /* RFC6265 5.2.4 The Path Attribute */ - if(cookie_path[0] != '/') + if(!len || (cookie_path[0] != '/')) /* Let cookie-path be the default-path. */ - return strdup("/"); + return curlx_strdup("/"); /* remove trailing slash when path is non-empty */ /* convert /hoge/ to /hoge */ @@ -303,34 +249,6 @@ static char *sanitize_cookie_path(const char *cookie_path) return Curl_memdup0(cookie_path, len); } -/* - * Load cookies from all given cookie files (CURLOPT_COOKIEFILE). - * - * NOTE: OOM or cookie parsing failures are ignored. - */ -void Curl_cookie_loadfiles(struct Curl_easy *data) -{ - struct curl_slist *list = data->state.cookielist; - if(list) { - Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); - while(list) { - struct CookieInfo *ci = - Curl_cookie_init(data, list->data, data->cookies, - data->set.cookiesession); - if(!ci) - /* - * Failure may be due to OOM or a bad cookie; both are ignored - * but only the first should be - */ - infof(data, "ignoring failed cookie_init for %s", list->data); - else - data->cookies = ci; - list = list->next; - } - Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); - } -} - /* * strstore * @@ -340,15 +258,17 @@ void Curl_cookie_loadfiles(struct Curl_easy *data) * parsing in a last-wins scenario. The caller is responsible for checking * for OOM errors. */ -static void strstore(char **str, const char *newstr, size_t len) +static CURLcode strstore(char **str, const char *newstr, size_t len) { DEBUGASSERT(str); - free(*str); if(!len) { len++; newstr = ""; } *str = Curl_memdup0(newstr, len); + if(!*str) + return CURLE_OUT_OF_MEMORY; + return CURLE_OK; } /* @@ -390,7 +310,7 @@ static void remove_expired(struct CookieInfo *ci) if(co->expires) { if(co->expires < now) { Curl_node_remove(n); - freecookie(co); + freecookie(co, TRUE); ci->numcookies--; } else if(co->expires < ci->next_expiration) @@ -433,37 +353,19 @@ static bool bad_domain(const char *domain, size_t len) fine. The prime reason for filtering out control bytes is that some HTTP servers return 400 for requests that contain such. */ -static bool invalid_octets(const char *ptr) +static bool invalid_octets(const char *ptr, size_t len) { const unsigned char *p = (const unsigned char *)ptr; /* Reject all bytes \x01 - \x1f (*except* \x09, TAB) + \x7f */ - while(*p) { + while(len && *p) { if(((*p != 9) && (*p < 0x20)) || (*p == 0x7f)) return TRUE; p++; + len--; } return FALSE; } -#define CERR_OK 0 -#define CERR_TOO_LONG 1 /* input line too long */ -#define CERR_TAB 2 /* in a wrong place */ -#define CERR_TOO_BIG 3 /* name/value too large */ -#define CERR_BAD 4 /* deemed incorrect */ -#define CERR_NO_SEP 5 /* semicolon problem */ -#define CERR_NO_NAME_VALUE 6 /* name or value problem */ -#define CERR_INVALID_OCTET 7 /* bad content */ -#define CERR_BAD_SECURE 8 /* secure in a bad place */ -#define CERR_OUT_OF_MEMORY 9 -#define CERR_NO_TAILMATCH 10 -#define CERR_COMMENT 11 /* a commented line */ -#define CERR_RANGE 12 /* expire range problem */ -#define CERR_FIELDS 13 /* incomplete netscape line */ -#ifdef USE_LIBPSL -#define CERR_PSL 14 /* a public suffix */ -#endif -#define CERR_LIVE_WINS 15 - /* The maximum length we accept a date string for the 'expire' keyword. The standard date formats are within the 30 bytes range. This adds an extra margin just to make sure it realistically works with what is used out @@ -471,10 +373,64 @@ static bool invalid_octets(const char *ptr) */ #define MAX_DATE_LENGTH 80 -static int +#define COOKIE_NAME 0 +#define COOKIE_VALUE 1 +#define COOKIE_DOMAIN 2 +#define COOKIE_PATH 3 + +#define COOKIE_PIECES 4 /* the list above */ + +static CURLcode storecookie(struct Cookie *co, struct Curl_str *cp, + const char *path, const char *domain) +{ + CURLcode result; + result = strstore(&co->name, curlx_str(&cp[COOKIE_NAME]), + curlx_strlen(&cp[COOKIE_NAME])); + if(!result) + result = strstore(&co->value, curlx_str(&cp[COOKIE_VALUE]), + curlx_strlen(&cp[COOKIE_VALUE])); + if(!result) { + size_t plen = 0; + if(curlx_strlen(&cp[COOKIE_PATH])) { + path = curlx_str(&cp[COOKIE_PATH]); + plen = curlx_strlen(&cp[COOKIE_PATH]); + } + else if(path) { + /* No path was given in the header line, set the default */ + const char *endslash = strrchr(path, '/'); + if(endslash) + plen = (endslash - path + 1); /* include end slash */ + else + plen = strlen(path); + } + + if(path) { + co->path = sanitize_cookie_path(path, plen); + if(!co->path) + result = CURLE_OUT_OF_MEMORY; + } + } + if(!result) { + if(curlx_strlen(&cp[COOKIE_DOMAIN])) + result = strstore(&co->domain, curlx_str(&cp[COOKIE_DOMAIN]), + curlx_strlen(&cp[COOKIE_DOMAIN])); + else if(domain) { + /* no domain was given in the header line, set the default */ + co->domain = curlx_strdup(domain); + if(!co->domain) + result = CURLE_OUT_OF_MEMORY; + } + } + return result; +} + +/* this function return errors on OOM etc, not on plain cookie format + problems */ +static CURLcode parse_cookie_header(struct Curl_easy *data, struct Cookie *co, struct CookieInfo *ci, + bool *okay, /* if the cookie was fine */ const char *ptr, const char *domain, /* default domain */ const char *path, /* full path used when this cookie is @@ -484,121 +440,97 @@ parse_cookie_header(struct Curl_easy *data, origin */ { /* This line was read off an HTTP-header */ - time_t now; + time_t now = 0; size_t linelength = strlen(ptr); + CURLcode result = CURLE_OK; + struct Curl_str cookie[COOKIE_PIECES]; + *okay = FALSE; if(linelength > MAX_COOKIE_LINE) /* discard overly long lines at once */ - return CERR_TOO_LONG; + return CURLE_OK; - now = time(NULL); + /* memset instead of initializer because gcc 4.8.1 is silly */ + memset(cookie, 0, sizeof(cookie)); do { struct Curl_str name; struct Curl_str val; /* we have a = pair or a stand-alone word here */ if(!curlx_str_cspn(&ptr, &name, ";\t\r\n=")) { - bool done = FALSE; bool sep = FALSE; curlx_str_trimblanks(&name); if(!curlx_str_single(&ptr, '=')) { sep = TRUE; /* a '=' was used */ - if(!curlx_str_cspn(&ptr, &val, ";\r\n")) { + if(!curlx_str_cspn(&ptr, &val, ";\r\n")) curlx_str_trimblanks(&val); - - /* Reject cookies with a TAB inside the value */ - if(memchr(curlx_str(&val), '\t', curlx_strlen(&val))) { - infof(data, "cookie contains TAB, dropping"); - return CERR_TAB; - } - } } - else { + else curlx_str_init(&val); - } - - /* - * Check for too long individual name or contents, or too long - * combination of name + contents. Chrome and Firefox support 4095 or - * 4096 bytes combo - */ - if(curlx_strlen(&name) >= (MAX_NAME-1) || - curlx_strlen(&val) >= (MAX_NAME-1) || - ((curlx_strlen(&name) + curlx_strlen(&val)) > MAX_NAME)) { - infof(data, "oversized cookie dropped, name/val %zu + %zu bytes", - curlx_strlen(&name), curlx_strlen(&val)); - return CERR_TOO_BIG; - } - /* - * Check if we have a reserved prefix set before anything else, as we - * otherwise have to test for the prefix in both the cookie name and - * "the rest". Prefixes must start with '__' and end with a '-', so - * only test for names where that can possibly be true. - */ - if(!strncmp("__Secure-", curlx_str(&name), 9)) - co->prefix_secure = TRUE; - else if(!strncmp("__Host-", curlx_str(&name), 7)) - co->prefix_host = TRUE; + if(!curlx_strlen(&cookie[COOKIE_NAME])) { + /* The first name/value pair is the actual cookie name */ + if(!sep || + /* Bad name/value pair. */ + invalid_octets(curlx_str(&name), curlx_strlen(&name)) || + invalid_octets(curlx_str(&val), curlx_strlen(&val)) || + !curlx_strlen(&name)) { + infof(data, "invalid octets in name/value, cookie dropped"); + return CURLE_OK; + } - /* - * Use strstore() below to properly deal with received cookie - * headers that have the same string property set more than once, - * and then we use the last one. - */ + /* + * Check for too long individual name or contents, or too long + * combination of name + contents. Chrome and Firefox support 4095 or + * 4096 bytes combo + */ + if(curlx_strlen(&name) >= (MAX_NAME - 1) || + curlx_strlen(&val) >= (MAX_NAME - 1) || + ((curlx_strlen(&name) + curlx_strlen(&val)) > MAX_NAME)) { + infof(data, "oversized cookie dropped, name/val %zu + %zu bytes", + curlx_strlen(&name), curlx_strlen(&val)); + return CURLE_OK; + } - if(!co->name) { - /* The very first name/value pair is the actual cookie name */ - if(!sep) - /* Bad name/value pair. */ - return CERR_NO_SEP; + /* Reject cookies with a TAB inside the value */ + if(curlx_strlen(&val) && + memchr(curlx_str(&val), '\t', curlx_strlen(&val))) { + infof(data, "cookie contains TAB, dropping"); + return CURLE_OK; + } - strstore(&co->name, curlx_str(&name), curlx_strlen(&name)); - strstore(&co->value, curlx_str(&val), curlx_strlen(&val)); - done = TRUE; - if(!co->name || !co->value) - return CERR_NO_NAME_VALUE; + /* Check if we have a reserved prefix set. */ + if(!strncmp("__Secure-", curlx_str(&name), 9)) + co->prefix_secure = TRUE; + else if(!strncmp("__Host-", curlx_str(&name), 7)) + co->prefix_host = TRUE; - if(invalid_octets(co->value) || invalid_octets(co->name)) { - infof(data, "invalid octets in name/value, cookie dropped"); - return CERR_INVALID_OCTET; - } + cookie[COOKIE_NAME] = name; + cookie[COOKIE_VALUE] = val; } - else if(!curlx_strlen(&val)) { + else if(!sep) { /* - * this was a "=" with no content, and we must allow - * 'secure' and 'httponly' specified this weirdly + * this is a "" with no content */ - done = TRUE; + /* * secure cookies are only allowed to be set when the connection is * using a secure protocol, or when the cookie is being set by * reading from file */ if(curlx_str_casecompare(&name, "secure")) { - if(secure || !ci->running) { + if(secure || !ci->running) co->secure = TRUE; - } else { - return CERR_BAD_SECURE; + infof(data, "skipped cookie because not 'secure'"); + return CURLE_OK; } } else if(curlx_str_casecompare(&name, "httponly")) co->httponly = TRUE; - else if(sep) - /* there was a '=' so we are not done parsing this field */ - done = FALSE; } - if(done) - ; else if(curlx_str_casecompare(&name, "path")) { - strstore(&co->path, curlx_str(&val), curlx_strlen(&val)); - if(!co->path) - return CERR_OUT_OF_MEMORY; - free(co->spath); /* if this is set again */ - co->spath = sanitize_cookie_path(co->path); - if(!co->spath) - return CERR_OUT_OF_MEMORY; + cookie[COOKIE_PATH] = val; } else if(curlx_str_casecompare(&name, "domain") && curlx_strlen(&val)) { bool is_ip; @@ -623,16 +555,13 @@ parse_cookie_header(struct Curl_easy *data, is_ip = Curl_host_is_ipnum(domain ? domain : curlx_str(&val)); - if(!domain - || (is_ip && !strncmp(curlx_str(&val), domain, - curlx_strlen(&val)) && - (curlx_strlen(&val) == strlen(domain))) - || (!is_ip && cookie_tailmatch(curlx_str(&val), + if(!domain || + (is_ip && + !strncmp(curlx_str(&val), domain, curlx_strlen(&val)) && + (curlx_strlen(&val) == strlen(domain))) || + (!is_ip && cookie_tailmatch(curlx_str(&val), curlx_strlen(&val), domain))) { - strstore(&co->domain, curlx_str(&val), curlx_strlen(&val)); - if(!co->domain) - return CERR_OUT_OF_MEMORY; - + cookie[COOKIE_DOMAIN] = val; if(!is_ip) co->tailmatch = TRUE; /* we always do that if the domain name was given */ @@ -644,12 +573,9 @@ parse_cookie_header(struct Curl_easy *data, */ infof(data, "skipped cookie with bad tailmatch domain: %s", curlx_str(&val)); - return CERR_NO_TAILMATCH; + return CURLE_OK; } } - else if(curlx_str_casecompare(&name, "version")) { - /* just ignore */ - } else if(curlx_str_casecompare(&name, "max-age") && curlx_strlen(&val)) { /* * Defined in RFC2109: @@ -665,6 +591,8 @@ parse_cookie_header(struct Curl_easy *data, if(*maxage == '\"') maxage++; rc = curlx_str_number(&maxage, &co->expires, CURL_OFF_T_MAX); + if(!now) + now = time(NULL); switch(rc) { case STRE_OVERFLOW: /* overflow, used max value */ @@ -686,80 +614,47 @@ parse_cookie_header(struct Curl_easy *data, } cap_expires(now, co); } - else if(curlx_str_casecompare(&name, "expires") && curlx_strlen(&val)) { - if(!co->expires && (curlx_strlen(&val) < MAX_DATE_LENGTH)) { - /* - * Let max-age have priority. - * - * If the date cannot get parsed for whatever reason, the cookie - * will be treated as a session cookie - */ - char dbuf[MAX_DATE_LENGTH + 1]; - time_t date = 0; - memcpy(dbuf, curlx_str(&val), curlx_strlen(&val)); - dbuf[curlx_strlen(&val)] = 0; - if(!Curl_getdate_capped(dbuf, &date)) { - if(!date) - date++; - co->expires = (curl_off_t)date; - } - else - co->expires = 0; - cap_expires(now, co); + else if(curlx_str_casecompare(&name, "expires") && curlx_strlen(&val) && + !co->expires && (curlx_strlen(&val) < MAX_DATE_LENGTH)) { + /* + * Let max-age have priority. + * + * If the date cannot get parsed for whatever reason, the cookie + * will be treated as a session cookie + */ + char dbuf[MAX_DATE_LENGTH + 1]; + time_t date = 0; + memcpy(dbuf, curlx_str(&val), curlx_strlen(&val)); + dbuf[curlx_strlen(&val)] = 0; + if(!Curl_getdate_capped(dbuf, &date)) { + if(!date) + date++; + co->expires = (curl_off_t)date; } + else + co->expires = 0; + if(!now) + now = time(NULL); + cap_expires(now, co); } - - /* - * Else, this is the second (or more) name we do not know about! - */ } + } while(!curlx_str_single(&ptr, ';')); - if(curlx_str_single(&ptr, ';')) - break; - } while(1); - - if(!co->domain && domain) { - /* no domain was given in the header line, set the default */ - co->domain = strdup(domain); - if(!co->domain) - return CERR_OUT_OF_MEMORY; - } - - if(!co->path && path) { - /* - * No path was given in the header line, set the default. - */ - const char *endslash = strrchr(path, '/'); - if(endslash) { - size_t pathlen = (endslash - path + 1); /* include end slash */ - co->path = Curl_memdup0(path, pathlen); - if(co->path) { - co->spath = sanitize_cookie_path(co->path); - if(!co->spath) - return CERR_OUT_OF_MEMORY; - } - else - return CERR_OUT_OF_MEMORY; - } + if(curlx_strlen(&cookie[COOKIE_NAME])) { + /* the header was fine, now store the data */ + result = storecookie(co, &cookie[0], path, domain); + if(!result) + *okay = TRUE; } - - /* - * If we did not get a cookie name, or a bad one, the this is an illegal - * line so bail out. - */ - if(!co->name) - return CERR_BAD; - - data->req.setcookies++; - return CERR_OK; + return result; } -static int -parse_netscape(struct Cookie *co, - struct CookieInfo *ci, - const char *lineptr, - bool secure) /* TRUE if connection is over secure - origin */ +static CURLcode parse_netscape(struct Cookie *co, + struct CookieInfo *ci, + bool *okay, + const char *lineptr, + bool secure) /* TRUE if connection is over + secure origin */ { /* * This line is NOT an HTTP header style line, we do offer support for @@ -768,6 +663,7 @@ parse_netscape(struct Cookie *co, const char *ptr, *next; int fields; size_t len; + *okay = FALSE; /* * In 2008, Internet Explorer introduced HTTP-only cookies to prevent XSS @@ -780,9 +676,9 @@ parse_netscape(struct Cookie *co, co->httponly = TRUE; } - if(lineptr[0]=='#') + if(lineptr[0] == '#') /* do not even try the comments */ - return CERR_COMMENT; + return CURLE_OK; /* * Now loop through the fields and init the struct we already have @@ -795,13 +691,13 @@ parse_netscape(struct Cookie *co, next = (ptr[len] == '\t' ? &ptr[len + 1] : NULL); switch(fields) { case 0: - if(ptr[0]=='.') { /* skip preceding dots */ + if(ptr[0] == '.') { /* skip preceding dots */ ptr++; len--; } co->domain = Curl_memdup0(ptr, len); if(!co->domain) - return CERR_OUT_OF_MEMORY; + return CURLE_OUT_OF_MEMORY; break; case 1: /* @@ -815,23 +711,17 @@ parse_netscape(struct Cookie *co, /* The file format allows the path field to remain not filled in */ if(strncmp("TRUE", ptr, len) && strncmp("FALSE", ptr, len)) { /* only if the path does not look like a boolean option! */ - co->path = Curl_memdup0(ptr, len); + co->path = sanitize_cookie_path(ptr, len); if(!co->path) - return CERR_OUT_OF_MEMORY; - else { - co->spath = sanitize_cookie_path(co->path); - if(!co->spath) - return CERR_OUT_OF_MEMORY; - } + return CURLE_OUT_OF_MEMORY; break; } - /* this does not look like a path, make one up! */ - co->path = strdup("/"); - if(!co->path) - return CERR_OUT_OF_MEMORY; - co->spath = strdup("/"); - if(!co->spath) - return CERR_OUT_OF_MEMORY; + else { + /* this does not look like a path, make one up! */ + co->path = curlx_strdup("/"); + if(!co->path) + return CURLE_OUT_OF_MEMORY; + } fields++; /* add a field and fall down to secure */ FALLTHROUGH(); case 3: @@ -840,17 +730,17 @@ parse_netscape(struct Cookie *co, if(secure || ci->running) co->secure = TRUE; else - return CERR_BAD_SECURE; + return CURLE_OK; } break; case 4: if(curlx_str_number(&ptr, &co->expires, CURL_OFF_T_MAX)) - return CERR_RANGE; + return CURLE_OK; break; case 5: co->name = Curl_memdup0(ptr, len); if(!co->name) - return CERR_OUT_OF_MEMORY; + return CURLE_OUT_OF_MEMORY; else { /* For Netscape file format cookies we check prefix on the name */ if(curl_strnequal("__Secure-", co->name, 9)) @@ -862,30 +752,30 @@ parse_netscape(struct Cookie *co, case 6: co->value = Curl_memdup0(ptr, len); if(!co->value) - return CERR_OUT_OF_MEMORY; + return CURLE_OUT_OF_MEMORY; break; } } if(fields == 6) { /* we got a cookie with blank contents, fix it */ - co->value = strdup(""); + co->value = curlx_strdup(""); if(!co->value) - return CERR_OUT_OF_MEMORY; + return CURLE_OUT_OF_MEMORY; else fields++; } if(fields != 7) /* we did not find the sufficient number of fields */ - return CERR_FIELDS; + return CURLE_OK; - return CERR_OK; + *okay = TRUE; + return CURLE_OK; } -static int -is_public_suffix(struct Curl_easy *data, - struct Cookie *co, - const char *domain) +static bool is_public_suffix(struct Curl_easy *data, + struct Cookie *co, + const char *domain) { #ifdef USE_LIBPSL /* @@ -917,7 +807,7 @@ is_public_suffix(struct Curl_easy *data, if(!acceptable) { infof(data, "cookie '%s' dropped, domain '%s' must not " "set cookies for '%s'", co->name, domain, co->domain); - return CERR_PSL; + return TRUE; } } #else @@ -927,15 +817,15 @@ is_public_suffix(struct Curl_easy *data, DEBUGF(infof(data, "NO PSL to check set-cookie '%s' for domain=%s in %s", co->name, co->domain, domain)); #endif - return CERR_OK; + return FALSE; } -static int -replace_existing(struct Curl_easy *data, - struct Cookie *co, - struct CookieInfo *ci, - bool secure, - bool *replacep) +/* returns TRUE when replaced */ +static bool replace_existing(struct Curl_easy *data, + struct Cookie *co, + struct CookieInfo *ci, + bool secure, + bool *replacep) { bool replace_old = FALSE; struct Curl_llist_node *replace_n = NULL; @@ -956,7 +846,7 @@ replace_existing(struct Curl_easy *data, matching_domains = TRUE; if(matching_domains && /* the domains were identical */ - clist->spath && co->spath && /* both have paths */ + clist->path && co->path && /* both have paths */ clist->secure && !co->secure && !secure) { size_t cllen; const char *sep = NULL; @@ -968,18 +858,18 @@ replace_existing(struct Curl_easy *data, * "/loginhelper" is ok. */ - DEBUGASSERT(clist->spath[0]); - if(clist->spath[0]) - sep = strchr(clist->spath + 1, '/'); + DEBUGASSERT(clist->path[0]); + if(clist->path[0]) + sep = strchr(clist->path + 1, '/'); if(sep) - cllen = sep - clist->spath; + cllen = sep - clist->path; else - cllen = strlen(clist->spath); + cllen = strlen(clist->path); - if(curl_strnequal(clist->spath, co->spath, cllen)) { + if(curl_strnequal(clist->path, co->path, cllen)) { infof(data, "cookie '%s' for domain '%s' dropped, would " "overlay an existing cookie", co->name, co->domain); - return CERR_BAD_SECURE; + return FALSE; } } } @@ -989,7 +879,7 @@ replace_existing(struct Curl_easy *data, if(clist->domain && co->domain) { if(curl_strequal(clist->domain, co->domain) && - (clist->tailmatch == co->tailmatch)) + (clist->tailmatch == co->tailmatch)) /* The domains are identical */ replace_old = TRUE; } @@ -999,10 +889,10 @@ replace_existing(struct Curl_easy *data, if(replace_old) { /* the domains were identical */ - if(clist->spath && co->spath && - !curl_strequal(clist->spath, co->spath)) + if(clist->path && co->path && + !curl_strequal(clist->path, co->path)) replace_old = FALSE; - else if(!clist->spath != !co->spath) + else if(!clist->path != !co->path) replace_old = FALSE; } @@ -1013,7 +903,7 @@ replace_existing(struct Curl_easy *data, * was read from a file and thus is not "live". "live" cookies are * preferred so the new cookie is freed. */ - return CERR_LIVE_WINS; + return FALSE; } if(replace_old) replace_n = n; @@ -1029,10 +919,10 @@ replace_existing(struct Curl_easy *data, Curl_node_remove(replace_n); /* free the old cookie */ - freecookie(repl); + freecookie(repl, TRUE); } *replacep = replace_old; - return CERR_OK; + return TRUE; } /* @@ -1042,10 +932,8 @@ replace_existing(struct Curl_easy *data, * sometimes we get an IP-only hostname, and that might also be a numerical * IPv6 address. * - * Returns NULL on out of memory or invalid cookie. This is suboptimal, - * as they should be treated separately. */ -struct Cookie * +CURLcode Curl_cookie_add(struct Curl_easy *data, struct CookieInfo *ci, bool httpheader, /* TRUE if HTTP header-style line */ @@ -1057,27 +945,28 @@ Curl_cookie_add(struct Curl_easy *data, unless set */ bool secure) /* TRUE if connection is over secure origin */ { + struct Cookie comem; struct Cookie *co; size_t myhash; - int rc; + CURLcode result; bool replaces = FALSE; + bool okay; DEBUGASSERT(data); DEBUGASSERT(MAX_SET_COOKIE_AMOUNT <= 255); /* counter is an unsigned char */ if(data->req.setcookies >= MAX_SET_COOKIE_AMOUNT) - return NULL; + return CURLE_OK; /* silently ignore */ - /* First, alloc and init a new struct for it */ - co = calloc(1, sizeof(struct Cookie)); - if(!co) - return NULL; /* bail out if we are this low on memory */ + co = &comem; + memset(co, 0, sizeof(comem)); if(httpheader) - rc = parse_cookie_header(data, co, ci, lineptr, domain, path, secure); + result = parse_cookie_header(data, co, ci, &okay, + lineptr, domain, path, secure); else - rc = parse_netscape(co, ci, lineptr, secure); + result = parse_netscape(co, ci, &okay, lineptr, secure); - if(rc) + if(result || !okay) goto fail; if(co->prefix_secure && !co->secure) @@ -1089,7 +978,7 @@ Curl_cookie_add(struct Curl_easy *data, * The __Host- prefix requires the cookie to be secure, have a "/" path * and not have a domain set. */ - if(co->secure && co->path && strcmp(co->path, "/") == 0 && !co->tailmatch) + if(co->secure && co->path && !strcmp(co->path, "/") && !co->tailmatch) ; else goto fail; @@ -1116,9 +1005,17 @@ Curl_cookie_add(struct Curl_easy *data, if(is_public_suffix(data, co, domain)) goto fail; - if(replace_existing(data, co, ci, secure, &replaces)) + if(!replace_existing(data, co, ci, secure, &replaces)) goto fail; + /* clone the stack struct into heap */ + co = Curl_memdup(&comem, sizeof(comem)); + if(!co) { + co = &comem; + result = CURLE_OUT_OF_MEMORY; + goto fail; /* bail out if we are this low on memory */ + } + /* add this cookie to the list */ myhash = cookiehash(co->domain); Curl_llist_append(&ci->cookielist[myhash], co, &co->node); @@ -1127,7 +1024,7 @@ Curl_cookie_add(struct Curl_easy *data, /* Only show this when NOT reading the cookies from a file */ infof(data, "%s cookie %s=\"%s\" for domain %s, path %s, " "expire %" FMT_OFF_T, - replaces ? "Replaced":"Added", co->name, co->value, + replaces ? "Replaced" : "Added", co->name, co->value, co->domain, co->path, co->expires); if(!replaces) @@ -1140,13 +1037,15 @@ Curl_cookie_add(struct Curl_easy *data, if(co->expires && (co->expires < ci->next_expiration)) ci->next_expiration = co->expires; - return co; + if(httpheader) + data->req.setcookies++; + + return result; fail: - freecookie(co); - return NULL; + freecookie(co, FALSE); + return result; } - /* * Curl_cookie_init() * @@ -1159,54 +1058,69 @@ Curl_cookie_add(struct Curl_easy *data, * Note that 'data' might be called as NULL pointer. If data is NULL, 'file' * will be ignored. * - * Returns NULL on out of memory. Invalid cookies are ignored. + * Returns NULL on out of memory. */ -struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, - const char *file, - struct CookieInfo *ci, - bool newsession) +struct CookieInfo *Curl_cookie_init(void) { - FILE *handle = NULL; + int i; + struct CookieInfo *ci = curlx_calloc(1, sizeof(struct CookieInfo)); + if(!ci) + return NULL; - if(!ci) { - int i; + /* This does not use the destructor callback since we want to add + and remove to lists while keeping the cookie struct intact */ + for(i = 0; i < COOKIE_HASH_SIZE; i++) + Curl_llist_init(&ci->cookielist[i], NULL); + /* + * Initialize the next_expiration time to signal that we do not have enough + * information yet. + */ + ci->next_expiration = CURL_OFF_T_MAX; - /* we did not get a struct, create one */ - ci = calloc(1, sizeof(struct CookieInfo)); - if(!ci) - return NULL; /* failed to get memory */ + return ci; +} - /* This does not use the destructor callback since we want to add - and remove to lists while keeping the cookie struct intact */ - for(i = 0; i < COOKIE_HASH_SIZE; i++) - Curl_llist_init(&ci->cookielist[i], NULL); - /* - * Initialize the next_expiration time to signal that we do not have enough - * information yet. - */ - ci->next_expiration = CURL_OFF_T_MAX; - } - ci->newsession = newsession; /* new session? */ +/* + * cookie_load() + * + * Reads cookies from a local file. This is always called before any cookies + * are set. If file is "-" then STDIN is read. + * + * If 'newsession' is TRUE, discard all "session cookies" on read from file. + * + */ +static CURLcode cookie_load(struct Curl_easy *data, const char *file, + struct CookieInfo *ci, bool newsession) +{ + FILE *handle = NULL; + CURLcode result = CURLE_OK; + FILE *fp = NULL; + DEBUGASSERT(ci); + DEBUGASSERT(data); + DEBUGASSERT(file); - if(data) { - FILE *fp = NULL; - if(file && *file) { - if(!strcmp(file, "-")) - fp = stdin; - else { - fp = curlx_fopen(file, "rb"); - if(!fp) - infof(data, "WARNING: failed to open cookie file \"%s\"", file); - else - handle = fp; - } + ci->newsession = newsession; /* new session? */ + ci->running = FALSE; /* this is not running, this is init */ + + if(file && *file) { + if(!strcmp(file, "-")) + fp = stdin; + else { + fp = curlx_fopen(file, "rb"); + if(!fp) + infof(data, "WARNING: failed to open cookie file \"%s\"", file); + else + handle = fp; } + } - ci->running = FALSE; /* this is not running, this is init */ - if(fp) { - struct dynbuf buf; - curlx_dyn_init(&buf, MAX_COOKIE_LINE); - while(Curl_get_line(&buf, fp)) { + if(fp) { + struct dynbuf buf; + bool eof = FALSE; + curlx_dyn_init(&buf, MAX_COOKIE_LINE); + do { + result = Curl_get_line(&buf, fp, &eof); + if(!result) { const char *lineptr = curlx_dyn_ptr(&buf); bool headerline = FALSE; if(checkprefix("Set-Cookie:", lineptr)) { @@ -1216,24 +1130,55 @@ struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, curlx_str_passblanks(&lineptr); } - Curl_cookie_add(data, ci, headerline, TRUE, lineptr, NULL, NULL, TRUE); + result = Curl_cookie_add(data, ci, headerline, TRUE, lineptr, NULL, + NULL, TRUE); + /* File reading cookie failures are not propagated back to the + caller because there is no way to do that */ } - curlx_dyn_free(&buf); /* free the line buffer */ + } while(!result && !eof); + curlx_dyn_free(&buf); /* free the line buffer */ - /* - * Remove expired cookies from the hash. We must make sure to run this - * after reading the file, and not on every cookie. - */ - remove_expired(ci); + /* + * Remove expired cookies from the hash. We must make sure to run this + * after reading the file, and not on every cookie. + */ + remove_expired(ci); - if(handle) - curlx_fclose(handle); - } - data->state.cookie_engine = TRUE; + if(handle) + curlx_fclose(handle); } + data->state.cookie_engine = TRUE; ci->running = TRUE; /* now, we are running */ - return ci; + return result; +} + +/* + * Load cookies from all given cookie files (CURLOPT_COOKIEFILE). + */ +CURLcode Curl_cookie_loadfiles(struct Curl_easy *data) +{ + CURLcode result = CURLE_OK; + struct curl_slist *list = data->state.cookielist; + if(list) { + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + if(!data->cookies) + data->cookies = Curl_cookie_init(); + if(!data->cookies) + result = CURLE_OUT_OF_MEMORY; + else { + data->state.cookie_engine = TRUE; + while(list) { + result = cookie_load(data, list->data, data->cookies, + data->set.cookiesession); + if(result) + break; + list = list->next; + } + } + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); + } + return result; } /* @@ -1290,7 +1235,7 @@ static int cookie_sort_ct(const void *p1, const void *p2) bool Curl_secure_context(struct connectdata *conn, const char *host) { - return conn->handler->protocol&(CURLPROTO_HTTPS|CURLPROTO_WSS) || + return conn->handler->protocol & (CURLPROTO_HTTPS | CURLPROTO_WSS) || curl_strequal("localhost", host) || !strcmp(host, "127.0.0.1") || !strcmp(host, "::1"); @@ -1305,12 +1250,13 @@ bool Curl_secure_context(struct connectdata *conn, const char *host) * * It shall only return cookies that have not expired. * - * Returns 0 when there is a list returned. Otherwise non-zero. + * 'okay' is TRUE when there is a list returned. */ -int Curl_cookie_getlist(struct Curl_easy *data, - struct connectdata *conn, - const char *host, - struct Curl_llist *list) +CURLcode Curl_cookie_getlist(struct Curl_easy *data, + struct connectdata *conn, + bool *okay, + const char *host, + struct Curl_llist *list) { size_t matches = 0; const bool is_ip = Curl_host_is_ipnum(host); @@ -1319,17 +1265,18 @@ int Curl_cookie_getlist(struct Curl_easy *data, const bool secure = Curl_secure_context(conn, host); struct CookieInfo *ci = data->cookies; const char *path = data->state.up.path; + CURLcode result = CURLE_OK; + *okay = FALSE; Curl_llist_init(list, NULL); if(!ci || !Curl_llist_count(&ci->cookielist[myhash])) - return 1; /* no cookie struct or no cookies in the struct */ + return CURLE_OK; /* no cookie struct or no cookies in the struct */ /* at first, remove expired cookies */ remove_expired(ci); - for(n = Curl_llist_head(&ci->cookielist[myhash]); - n; n = Curl_node_next(n)) { + for(n = Curl_llist_head(&ci->cookielist[myhash]); n; n = Curl_node_next(n)) { struct Cookie *co = Curl_node_elem(n); /* if the cookie requires we are secure we must only continue if we are! */ @@ -1339,7 +1286,7 @@ int Curl_cookie_getlist(struct Curl_easy *data, if(!co->domain || (co->tailmatch && !is_ip && cookie_tailmatch(co->domain, strlen(co->domain), host)) || - ((!co->tailmatch || is_ip) && curl_strequal(host, co->domain)) ) { + ((!co->tailmatch || is_ip) && curl_strequal(host, co->domain))) { /* * the right part of the host matches the domain stuff in the * cookie data @@ -1349,7 +1296,7 @@ int Curl_cookie_getlist(struct Curl_easy *data, * now check the left part of the path with the cookies path * requirement */ - if(!co->spath || pathmatch(co->spath, path) ) { + if(!co->path || pathmatch(co->path, path)) { /* * This is a match and we add it to the return-linked-list @@ -1376,9 +1323,11 @@ int Curl_cookie_getlist(struct Curl_easy *data, size_t i; /* alloc an array and store all cookie pointers */ - array = malloc(sizeof(struct Cookie *) * matches); - if(!array) + array = curlx_malloc(sizeof(struct Cookie *) * matches); + if(!array) { + result = CURLE_OUT_OF_MEMORY; goto fail; + } n = Curl_llist_head(list); @@ -1394,15 +1343,16 @@ int Curl_cookie_getlist(struct Curl_easy *data, for(i = 0; i < matches; i++) Curl_llist_append(list, array[i], &array[i]->getnode); - free(array); /* remove the temporary data again */ + curlx_free(array); /* remove the temporary data again */ } - return 0; /* success */ + *okay = TRUE; + return CURLE_OK; /* success */ fail: /* failure, clear up the allocated chain and return NULL */ Curl_llist_destroy(list, NULL); - return 2; /* error */ + return result; /* error */ } /* @@ -1420,7 +1370,7 @@ void Curl_cookie_clearall(struct CookieInfo *ci) struct Cookie *c = Curl_node_elem(n); struct Curl_llist_node *e = Curl_node_next(n); Curl_node_remove(n); - freecookie(c); + freecookie(c, TRUE); n = e; } } @@ -1449,7 +1399,7 @@ void Curl_cookie_clearsess(struct CookieInfo *ci) e = Curl_node_next(n); /* in case the node is removed, get it early */ if(!curr->expires) { Curl_node_remove(n); - freecookie(curr); + freecookie(curr, TRUE); ci->numcookies--; } } @@ -1465,7 +1415,7 @@ void Curl_cookie_cleanup(struct CookieInfo *ci) { if(ci) { Curl_cookie_clearall(ci); - free(ci); /* free the base struct as well */ + curlx_free(ci); /* free the base struct as well */ } } @@ -1479,14 +1429,14 @@ void Curl_cookie_cleanup(struct CookieInfo *ci) static char *get_netscape_format(const struct Cookie *co) { return curl_maprintf( - "%s" /* httponly preamble */ - "%s%s\t" /* domain */ - "%s\t" /* tailmatch */ - "%s\t" /* path */ - "%s\t" /* secure */ - "%" FMT_OFF_T "\t" /* expires */ - "%s\t" /* name */ - "%s", /* value */ + "%s" /* httponly preamble */ + "%s%s\t" /* domain */ + "%s\t" /* tailmatch */ + "%s\t" /* path */ + "%s\t" /* secure */ + "%" FMT_OFF_T "\t" /* expires */ + "%s\t" /* name */ + "%s", /* value */ co->httponly ? "#HttpOnly_" : "", /* * Make sure all domains are prefixed with a dot if they allow @@ -1548,7 +1498,7 @@ static CURLcode cookie_output(struct Curl_easy *data, struct Cookie **array; struct Curl_llist_node *n; - array = calloc(1, sizeof(struct Cookie *) * ci->numcookies); + array = curlx_calloc(1, sizeof(struct Cookie *) * ci->numcookies); if(!array) { error = CURLE_OUT_OF_MEMORY; goto error; @@ -1556,8 +1506,7 @@ static CURLcode cookie_output(struct Curl_easy *data, /* only sort the cookies with a domain property */ for(i = 0; i < COOKIE_HASH_SIZE; i++) { - for(n = Curl_llist_head(&ci->cookielist[i]); n; - n = Curl_node_next(n)) { + for(n = Curl_llist_head(&ci->cookielist[i]); n; n = Curl_node_next(n)) { struct Cookie *co = Curl_node_elem(n); if(!co->domain) continue; @@ -1570,22 +1519,21 @@ static CURLcode cookie_output(struct Curl_easy *data, for(i = 0; i < nvalid; i++) { char *format_ptr = get_netscape_format(array[i]); if(!format_ptr) { - free(array); + curlx_free(array); error = CURLE_OUT_OF_MEMORY; goto error; } curl_mfprintf(out, "%s\n", format_ptr); - free(format_ptr); + curlx_free(format_ptr); } - free(array); + curlx_free(array); } if(!use_stdout) { curlx_fclose(out); out = NULL; - if(tempstore && Curl_rename(tempstore, filename)) { - unlink(tempstore); + if(tempstore && curlx_rename(tempstore, filename)) { error = CURLE_WRITE_ERROR; goto error; } @@ -1596,13 +1544,16 @@ static CURLcode cookie_output(struct Curl_easy *data, * no need to inspect the error, any error case should have jumped into the * error block below. */ - free(tempstore); + curlx_free(tempstore); return CURLE_OK; error: if(out && !use_stdout) curlx_fclose(out); - free(tempstore); + if(tempstore) { + unlink(tempstore); + curlx_free(tempstore); + } return error; } @@ -1633,7 +1584,7 @@ static struct curl_slist *cookie_list(struct Curl_easy *data) } beg = Curl_slist_append_nodup(list, line); if(!beg) { - free(line); + curlx_free(line); curl_slist_free_all(list); return NULL; } @@ -1655,19 +1606,18 @@ struct curl_slist *Curl_cookie_list(struct Curl_easy *data) void Curl_flush_cookies(struct Curl_easy *data, bool cleanup) { - CURLcode res; - Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); /* only save the cookie file if a transfer was started (data->state.url is set), as otherwise the cookies were not completely initialized and there - might be cookie files that weren't loaded so saving the file is the wrong + might be cookie files that were not loaded so saving the file is the wrong thing. */ - if(data->set.str[STRING_COOKIEJAR] && data->state.url) { + if(data->set.str[STRING_COOKIEJAR] && Curl_bufref_ptr(&data->state.url)) { /* if we have a destination file for all the cookies to get dumped to */ - res = cookie_output(data, data->cookies, data->set.str[STRING_COOKIEJAR]); - if(res) + CURLcode result = cookie_output(data, data->cookies, + data->set.str[STRING_COOKIEJAR]); + if(result) infof(data, "WARNING: failed to save cookies in %s: %s", - data->set.str[STRING_COOKIEJAR], curl_easy_strerror(res)); + data->set.str[STRING_COOKIEJAR], curl_easy_strerror(result)); } if(cleanup && (!data->share || (data->cookies != data->share->cookies))) { @@ -1677,4 +1627,12 @@ void Curl_flush_cookies(struct Curl_easy *data, bool cleanup) Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); } +void Curl_cookie_run(struct Curl_easy *data) +{ + Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); + if(data->cookies) + data->cookies->running = TRUE; + Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); +} + #endif /* CURL_DISABLE_HTTP || CURL_DISABLE_COOKIES */ diff --git a/lib/cookie.h b/lib/cookie.h index 99aa20af7c4b..cbc7b748fc2b 100644 --- a/lib/cookie.h +++ b/lib/cookie.h @@ -25,34 +25,31 @@ ***************************************************************************/ #include "curl_setup.h" -#include - #include "llist.h" struct Cookie { - struct Curl_llist_node node; /* for the main cookie list */ + struct Curl_llist_node node; /* for the main cookie list */ struct Curl_llist_node getnode; /* for getlist */ - char *name; /* = value */ - char *value; /* name = */ - char *path; /* path = which is in Set-Cookie: */ - char *spath; /* sanitized cookie path */ - char *domain; /* domain = */ - curl_off_t expires; /* expires = */ - unsigned int creationtime; /* time when the cookie was written */ - BIT(tailmatch); /* tail-match the domain name */ - BIT(secure); /* the 'secure' keyword was used */ - BIT(livecookie); /* updated from a server, not a stored file */ - BIT(httponly); /* the httponly directive is present */ - BIT(prefix_secure); /* secure prefix is set */ - BIT(prefix_host); /* host prefix is set */ + char *name; /* = value */ + char *value; /* name = */ + char *path; /* canonical path */ + char *domain; /* domain = */ + curl_off_t expires; /* expires = */ + unsigned int creationtime; /* time when the cookie was written */ + BIT(tailmatch); /* tail-match the domain name */ + BIT(secure); /* the 'secure' keyword was used */ + BIT(livecookie); /* updated from server, not a stored file */ + BIT(httponly); /* the httponly directive is present */ + BIT(prefix_secure); /* secure prefix is set */ + BIT(prefix_host); /* host prefix is set */ }; /* * Available cookie prefixes, as defined in * draft-ietf-httpbis-rfc6265bis-02 */ -#define COOKIE_PREFIX__SECURE (1<<0) -#define COOKIE_PREFIX__HOST (1<<1) +#define COOKIE_PREFIX__SECURE (1 << 0) +#define COOKIE_PREFIX__HOST (1 << 1) #define COOKIE_HASH_SIZE 63 @@ -60,9 +57,9 @@ struct CookieInfo { /* linked lists of cookies we know of */ struct Curl_llist cookielist[COOKIE_HASH_SIZE]; curl_off_t next_expiration; /* the next time at which expiration happens */ - unsigned int numcookies; /* number of cookies in the "jar" */ - unsigned int lastct; /* last creation-time used in the jar */ - BIT(running); /* state info, for cookie adding information */ + unsigned int numcookies; /* number of cookies in the "jar" */ + unsigned int lastct; /* last creation-time used in the jar */ + BIT(running); /* state info, for cookie adding information */ BIT(newsession); /* new session, discard session cookies on load */ }; @@ -113,30 +110,31 @@ struct connectdata; */ bool Curl_secure_context(struct connectdata *conn, const char *host); -struct Cookie *Curl_cookie_add(struct Curl_easy *data, - struct CookieInfo *c, bool header, - bool noexpiry, const char *lineptr, - const char *domain, const char *path, - bool secure); -int Curl_cookie_getlist(struct Curl_easy *data, struct connectdata *conn, - const char *host, struct Curl_llist *list); +CURLcode Curl_cookie_add(struct Curl_easy *data, + struct CookieInfo *c, bool header, + bool noexpiry, const char *lineptr, + const char *domain, const char *path, + bool secure) WARN_UNUSED_RESULT; +CURLcode Curl_cookie_getlist(struct Curl_easy *data, struct connectdata *conn, + bool *okay, const char *host, + struct Curl_llist *list) WARN_UNUSED_RESULT; void Curl_cookie_clearall(struct CookieInfo *cookies); void Curl_cookie_clearsess(struct CookieInfo *cookies); #if defined(CURL_DISABLE_HTTP) || defined(CURL_DISABLE_COOKIES) #define Curl_cookie_list(x) NULL -#define Curl_cookie_loadfiles(x) Curl_nop_stmt -#define Curl_cookie_init(x,y,z,w) NULL +#define Curl_cookie_loadfiles(x) CURLE_OK +#define Curl_cookie_init() NULL +#define Curl_cookie_run(x) Curl_nop_stmt #define Curl_cookie_cleanup(x) Curl_nop_stmt -#define Curl_flush_cookies(x,y) Curl_nop_stmt +#define Curl_flush_cookies(x, y) Curl_nop_stmt #else void Curl_flush_cookies(struct Curl_easy *data, bool cleanup); void Curl_cookie_cleanup(struct CookieInfo *c); -struct CookieInfo *Curl_cookie_init(struct Curl_easy *data, - const char *file, struct CookieInfo *inc, - bool newsession); +struct CookieInfo *Curl_cookie_init(void); struct curl_slist *Curl_cookie_list(struct Curl_easy *data); -void Curl_cookie_loadfiles(struct Curl_easy *data); +CURLcode Curl_cookie_loadfiles(struct Curl_easy *data) WARN_UNUSED_RESULT; +void Curl_cookie_run(struct Curl_easy *data); #endif #endif /* HEADER_CURL_COOKIE_H */ diff --git a/lib/cshutdn.c b/lib/cshutdn.c index c2788e7780a4..c7f2d6610ab4 100644 --- a/lib/cshutdn.c +++ b/lib/cshutdn.c @@ -25,27 +25,19 @@ #include "curl_setup.h" -#include - #include "urldata.h" #include "url.h" #include "cfilters.h" #include "progress.h" #include "multiif.h" #include "multi_ev.h" -#include "sendf.h" +#include "curl_trc.h" #include "cshutdn.h" -#include "http_negotiate.h" -#include "http_ntlm.h" #include "sigpipe.h" #include "connect.h" #include "select.h" #include "curlx/strparse.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - static void cshutdn_run_conn_handler(struct Curl_easy *data, struct connectdata *conn) @@ -123,7 +115,6 @@ void Curl_cshutdn_run_once(struct Curl_easy *data, Curl_detach_connection(data); } - void Curl_cshutdn_terminate(struct Curl_easy *data, struct connectdata *conn, bool do_shutdown) @@ -231,15 +222,12 @@ static CURLcode cshutdn_wait(struct cshutdn *cshutdn, return result; } - static void cshutdn_perform(struct cshutdn *cshutdn, struct Curl_easy *data) { struct Curl_llist_node *e = Curl_llist_head(&cshutdn->list); struct Curl_llist_node *enext; struct connectdata *conn; - struct curltime *nowp = NULL; - struct curltime now; timediff_t next_expire_ms = 0, ms; bool done; @@ -259,11 +247,7 @@ static void cshutdn_perform(struct cshutdn *cshutdn, else { /* idata has one timer list, but maybe more than one connection. * Set EXPIRE_SHUTDOWN to the smallest time left for all. */ - if(!nowp) { - now = curlx_now(); - nowp = &now; - } - ms = Curl_conn_shutdown_timeleft(conn, nowp); + ms = Curl_conn_shutdown_timeleft(data, conn); if(ms && ms < next_expire_ms) next_expire_ms = ms; } @@ -271,15 +255,14 @@ static void cshutdn_perform(struct cshutdn *cshutdn, } if(next_expire_ms) - Curl_expire_ex(data, nowp, next_expire_ms, EXPIRE_SHUTDOWN); + Curl_expire_ex(data, next_expire_ms, EXPIRE_SHUTDOWN); } - static void cshutdn_terminate_all(struct cshutdn *cshutdn, struct Curl_easy *data, int timeout_ms) { - struct curltime started = curlx_now(); + struct curltime started = *Curl_pgrs_now(data); struct Curl_llist_node *e; SIGPIPE_VARIABLE(pipe_st); @@ -291,7 +274,7 @@ static void cshutdn_terminate_all(struct cshutdn *cshutdn, sigpipe_apply(data, &pipe_st); while(Curl_llist_head(&cshutdn->list)) { - timediff_t timespent; + timediff_t spent_ms; int remain_ms; cshutdn_perform(cshutdn, data); @@ -302,14 +285,14 @@ static void cshutdn_terminate_all(struct cshutdn *cshutdn, } /* wait for activity, timeout or "nothing" */ - timespent = curlx_timediff(curlx_now(), started); - if(timespent >= (timediff_t)timeout_ms) { + spent_ms = curlx_ptimediff_ms(Curl_pgrs_now(data), &started); + if(spent_ms >= (timediff_t)timeout_ms) { CURL_TRC_M(data, "[SHUTDOWN] shutdown finished, %s", - (timeout_ms > 0) ? "timeout" : "best effort done"); + (timeout_ms > 0) ? "timeout" : "best effort done"); break; } - remain_ms = timeout_ms - (int)timespent; + remain_ms = timeout_ms - (int)spent_ms; if(cshutdn_wait(cshutdn, data, remain_ms)) { CURL_TRC_M(data, "[SHUTDOWN] shutdown finished, aborted"); break; @@ -329,7 +312,6 @@ static void cshutdn_terminate_all(struct cshutdn *cshutdn, sigpipe_restore(&pipe_st); } - int Curl_cshutdn_init(struct cshutdn *cshutdn, struct Curl_multi *multi) { @@ -340,7 +322,6 @@ int Curl_cshutdn_init(struct cshutdn *cshutdn, return 0; /* good */ } - void Curl_cshutdn_destroy(struct cshutdn *cshutdn, struct Curl_easy *data) { @@ -392,7 +373,6 @@ size_t Curl_cshutdn_dest_count(struct Curl_easy *data, return 0; } - static CURLMcode cshutdn_update_ev(struct cshutdn *cshutdn, struct Curl_easy *data, struct connectdata *conn) @@ -408,14 +388,12 @@ static CURLMcode cshutdn_update_ev(struct cshutdn *cshutdn, return mresult; } - void Curl_cshutdn_add(struct cshutdn *cshutdn, struct connectdata *conn, size_t conns_in_pool) { struct Curl_easy *data = cshutdn->multi->admin; - size_t max_total = (cshutdn->multi->max_total_connections > 0) ? - (size_t)cshutdn->multi->max_total_connections : 0; + size_t max_total = cshutdn->multi->max_total_connections; /* Add the connection to our shutdown list for non-blocking shutdown * during multi processing. */ @@ -441,7 +419,6 @@ void Curl_cshutdn_add(struct cshutdn *cshutdn, conn->connection_id, Curl_llist_count(&cshutdn->list)); } - static void cshutdn_multi_socket(struct cshutdn *cshutdn, struct Curl_easy *data, curl_socket_t s) @@ -466,7 +443,6 @@ static void cshutdn_multi_socket(struct cshutdn *cshutdn, } } - void Curl_cshutdn_perform(struct cshutdn *cshutdn, struct Curl_easy *data, curl_socket_t s) @@ -488,8 +464,7 @@ void Curl_cshutdn_setfds(struct cshutdn *cshutdn, struct easy_pollset ps; Curl_pollset_init(&ps); - for(e = Curl_llist_head(&cshutdn->list); e; - e = Curl_node_next(e)) { + for(e = Curl_llist_head(&cshutdn->list); e; e = Curl_node_next(e)) { unsigned int i; struct connectdata *conn = Curl_node_elem(e); CURLcode result; @@ -503,20 +478,23 @@ void Curl_cshutdn_setfds(struct cshutdn *cshutdn, continue; for(i = 0; i < ps.n; i++) { + curl_socket_t sock = ps.sockets[i]; + if(!FDSET_SOCK(sock)) + continue; #ifdef __DJGPP__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Warith-conversion" #endif if(ps.actions[i] & CURL_POLL_IN) - FD_SET(ps.sockets[i], read_fd_set); + FD_SET(sock, read_fd_set); if(ps.actions[i] & CURL_POLL_OUT) - FD_SET(ps.sockets[i], write_fd_set); + FD_SET(sock, write_fd_set); #ifdef __DJGPP__ #pragma GCC diagnostic pop #endif if((ps.actions[i] & (CURL_POLL_OUT | CURL_POLL_IN)) && - ((int)ps.sockets[i] > *maxfd)) - *maxfd = (int)ps.sockets[i]; + ((int)sock > *maxfd)) + *maxfd = (int)sock; } } Curl_pollset_cleanup(&ps); @@ -537,8 +515,7 @@ unsigned int Curl_cshutdn_add_waitfds(struct cshutdn *cshutdn, CURLcode result; Curl_pollset_init(&ps); - for(e = Curl_llist_head(&cshutdn->list); e; - e = Curl_node_next(e)) { + for(e = Curl_llist_head(&cshutdn->list); e; e = Curl_node_next(e)) { conn = Curl_node_elem(e); Curl_pollset_reset(&ps); Curl_attach_connection(data, conn); @@ -565,8 +542,7 @@ CURLcode Curl_cshutdn_add_pollfds(struct cshutdn *cshutdn, struct connectdata *conn; Curl_pollset_init(&ps); - for(e = Curl_llist_head(&cshutdn->list); e; - e = Curl_node_next(e)) { + for(e = Curl_llist_head(&cshutdn->list); e; e = Curl_node_next(e)) { conn = Curl_node_elem(e); Curl_pollset_reset(&ps); Curl_attach_connection(data, conn); diff --git a/lib/cshutdn.h b/lib/cshutdn.h index 510d5bf50613..793b4c6c2c96 100644 --- a/lib/cshutdn.h +++ b/lib/cshutdn.h @@ -25,7 +25,6 @@ * ***************************************************************************/ -#include #include "curlx/timeval.h" struct connectdata; diff --git a/lib/curl_addrinfo.c b/lib/curl_addrinfo.c index e26ee656bda4..43dcfd25c790 100644 --- a/lib/curl_addrinfo.c +++ b/lib/curl_addrinfo.c @@ -24,8 +24,6 @@ #include "curl_setup.h" -#include - #ifdef HAVE_NETINET_IN_H # include #endif @@ -47,16 +45,11 @@ # include #endif -#include +#include /* for offsetof() */ #include "curl_addrinfo.h" #include "fake_addrinfo.h" #include "curlx/inet_pton.h" -#include "curlx/warnless.h" - -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" /* * Curl_freeaddrinfo() @@ -68,26 +61,24 @@ */ #if defined(__INTEL_COMPILER) && (__INTEL_COMPILER == 910) && \ - defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__) + defined(__OPTIMIZE__) && defined(__unix__) && defined(__i386__) /* workaround icc 9.1 optimizer issue */ # define vqualifier volatile #else # define vqualifier #endif -void -Curl_freeaddrinfo(struct Curl_addrinfo *cahead) +void Curl_freeaddrinfo(struct Curl_addrinfo *cahead) { struct Curl_addrinfo *vqualifier canext; struct Curl_addrinfo *ca; for(ca = cahead; ca; ca = canext) { canext = ca->ai_next; - free(ca); + curlx_free(ca); } } - #ifdef HAVE_GETADDRINFO /* * Curl_getaddrinfo_ex() @@ -102,12 +93,10 @@ Curl_freeaddrinfo(struct Curl_addrinfo *cahead) * There should be no single call to system's getaddrinfo() in the * whole library, any such call should be 'routed' through this one. */ - -int -Curl_getaddrinfo_ex(const char *nodename, - const char *servname, - const struct addrinfo *hints, - struct Curl_addrinfo **result) +int Curl_getaddrinfo_ex(const char *nodename, + const char *servname, + const struct addrinfo *hints, + struct Curl_addrinfo **result) { const struct addrinfo *ai; struct addrinfo *aihead; @@ -146,7 +135,7 @@ Curl_getaddrinfo_ex(const char *nodename, if((size_t)ai->ai_addrlen < ss_size) continue; - ca = malloc(sizeof(struct Curl_addrinfo) + ss_size + namelen); + ca = curlx_malloc(sizeof(struct Curl_addrinfo) + ss_size + namelen); if(!ca) { error = EAI_MEMORY; break; @@ -180,7 +169,6 @@ Curl_getaddrinfo_ex(const char *nodename, if(calast) calast->ai_next = ca; calast = ca; - } /* destroy the addrinfo list */ @@ -212,7 +200,6 @@ Curl_getaddrinfo_ex(const char *nodename, } #endif /* HAVE_GETADDRINFO */ - /* * Curl_he2ai() * @@ -252,10 +239,8 @@ Curl_getaddrinfo_ex(const char *nodename, * * #define h_addr h_addr_list[0] */ - #if !(defined(HAVE_GETADDRINFO) && defined(HAVE_GETADDRINFO_THREADSAFE)) -struct Curl_addrinfo * -Curl_he2ai(const struct hostent *he, int port) +struct Curl_addrinfo *Curl_he2ai(const struct hostent *he, int port) { struct Curl_addrinfo *ai; struct Curl_addrinfo *prevai = NULL; @@ -285,7 +270,7 @@ Curl_he2ai(const struct hostent *he, int port) ss_size = sizeof(struct sockaddr_in); /* allocate memory to hold the struct, the address and the name */ - ai = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + namelen); + ai = curlx_calloc(1, sizeof(struct Curl_addrinfo) + ss_size + namelen); if(!ai) { result = CURLE_OUT_OF_MEMORY; break; @@ -347,16 +332,15 @@ Curl_he2ai(const struct hostent *he, int port) #endif /* - * Curl_ip2addr() + * ip2addr() * * This function takes an Internet address, in binary form, as input parameter * along with its address family and the string version of the address, and it * returns a Curl_addrinfo chain filled in correctly with information for the * given address/host */ - -struct Curl_addrinfo * -Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port) +static CURLcode ip2addr(struct Curl_addrinfo **addrp, int af, + const void *inaddr, const char *hostname, int port) { struct Curl_addrinfo *ai; size_t addrsize; @@ -369,6 +353,7 @@ Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port) DEBUGASSERT(inaddr && hostname); namelen = strlen(hostname) + 1; + *addrp = NULL; if(af == AF_INET) addrsize = sizeof(struct sockaddr_in); @@ -377,12 +362,12 @@ Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port) addrsize = sizeof(struct sockaddr_in6); #endif else - return NULL; + return CURLE_BAD_FUNCTION_ARGUMENT; /* allocate memory to hold the struct, the address and the name */ - ai = calloc(1, sizeof(struct Curl_addrinfo) + addrsize + namelen); + ai = curlx_calloc(1, sizeof(struct Curl_addrinfo) + addrsize + namelen); if(!ai) - return NULL; + return CURLE_OUT_OF_MEMORY; /* put the address after the struct */ ai->ai_addr = (void *)((char *)ai + sizeof(struct Curl_addrinfo)); /* then put the name after the address */ @@ -412,29 +397,46 @@ Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port) break; #endif } - - return ai; + *addrp = ai; + return CURLE_OK; } /* * Given an IPv4 or IPv6 dotted string address, this converts it to a proper * allocated Curl_addrinfo struct and returns it. */ -struct Curl_addrinfo *Curl_str2addr(char *address, int port) +CURLcode Curl_str2addr(const char *address, int port, + struct Curl_addrinfo **addrp) { struct in_addr in; if(curlx_inet_pton(AF_INET, address, &in) > 0) /* This is a dotted IP address 123.123.123.123-style */ - return Curl_ip2addr(AF_INET, &in, address, port); + return ip2addr(addrp, AF_INET, &in, address, port); #ifdef USE_IPV6 { struct in6_addr in6; if(curlx_inet_pton(AF_INET6, address, &in6) > 0) /* This is a dotted IPv6 address ::1-style */ - return Curl_ip2addr(AF_INET6, &in6, address, port); + return ip2addr(addrp, AF_INET6, &in6, address, port); } #endif - return NULL; /* bad input format */ + return CURLE_BAD_FUNCTION_ARGUMENT; /* bad input format */ +} + +bool Curl_is_ipaddr(const char *address) +{ + struct in_addr in; + if(curlx_inet_pton(AF_INET, address, &in) > 0) + return TRUE; +#ifdef USE_IPV6 + { + struct in6_addr in6; + if(curlx_inet_pton(AF_INET6, address, &in6) > 0) + /* This is a dotted IPv6 address ::1-style */ + return TRUE; + } +#endif + return FALSE; } #ifdef USE_UNIX_SOCKETS @@ -452,18 +454,19 @@ struct Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, *longpath = FALSE; - ai = calloc(1, sizeof(struct Curl_addrinfo) + sizeof(struct sockaddr_un)); + ai = curlx_calloc(1, + sizeof(struct Curl_addrinfo) + sizeof(struct sockaddr_un)); if(!ai) return NULL; ai->ai_addr = (void *)((char *)ai + sizeof(struct Curl_addrinfo)); - sa_un = (void *) ai->ai_addr; + sa_un = (void *)ai->ai_addr; sa_un->sun_family = AF_UNIX; /* sun_path must be able to store the null-terminated path */ path_len = strlen(path) + 1; if(path_len > sizeof(sa_un->sun_path)) { - free(ai); + curlx_free(ai); *longpath = TRUE; return NULL; } @@ -492,10 +495,8 @@ struct Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, * family otherwise present in memdebug.c. I put these ones here since they * require a bunch of structs I did not want to include in memdebug.c */ - -void -curl_dbg_freeaddrinfo(struct addrinfo *freethis, - int line, const char *source) +void curl_dbg_freeaddrinfo(struct addrinfo *freethis, + int line, const char *source) { curl_dbg_log("ADDR %s:%d freeaddrinfo(%p)\n", source, line, (void *)freethis); @@ -517,7 +518,6 @@ curl_dbg_freeaddrinfo(struct addrinfo *freethis, } #endif /* CURLDEBUG && HAVE_FREEADDRINFO */ - #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) /* * curl_dbg_getaddrinfo() @@ -526,13 +526,11 @@ curl_dbg_freeaddrinfo(struct addrinfo *freethis, * family otherwise present in memdebug.c. I put these ones here since they * require a bunch of structs I did not want to include in memdebug.c */ - -int -curl_dbg_getaddrinfo(const char *hostname, - const char *service, - const struct addrinfo *hints, - struct addrinfo **result, - int line, const char *source) +int curl_dbg_getaddrinfo(const char *hostname, + const char *service, + const struct addrinfo *hints, + struct addrinfo **result, + int line, const char *source) { #ifdef USE_LWIPSOCK int res = lwip_getaddrinfo(hostname, service, hints, result); @@ -550,11 +548,10 @@ curl_dbg_getaddrinfo(const char *hostname, #endif if(res == 0) /* success */ - curl_dbg_log("ADDR %s:%d getaddrinfo() = %p\n", - source, line, (void *)*result); + curl_dbg_log("ADDR %s:%d getaddrinfo() = %p\n", source, line, + (void *)*result); else - curl_dbg_log("ADDR %s:%d getaddrinfo() failed\n", - source, line); + curl_dbg_log("ADDR %s:%d getaddrinfo() failed\n", source, line); return res; } #endif /* CURLDEBUG && HAVE_GETADDRINFO */ diff --git a/lib/curl_addrinfo.h b/lib/curl_addrinfo.h index 2303e95e314e..378b31ed05da 100644 --- a/lib/curl_addrinfo.h +++ b/lib/curl_addrinfo.h @@ -60,26 +60,21 @@ struct Curl_addrinfo { struct Curl_addrinfo *ai_next; }; -void -Curl_freeaddrinfo(struct Curl_addrinfo *cahead); +void Curl_freeaddrinfo(struct Curl_addrinfo *cahead); #ifdef HAVE_GETADDRINFO -int -Curl_getaddrinfo_ex(const char *nodename, - const char *servname, - const struct addrinfo *hints, - struct Curl_addrinfo **result); +int Curl_getaddrinfo_ex(const char *nodename, + const char *servname, + const struct addrinfo *hints, + struct Curl_addrinfo **result); #endif #if !(defined(HAVE_GETADDRINFO) && defined(HAVE_GETADDRINFO_THREADSAFE)) -struct Curl_addrinfo * -Curl_he2ai(const struct hostent *he, int port); +struct Curl_addrinfo *Curl_he2ai(const struct hostent *he, int port); #endif -struct Curl_addrinfo * -Curl_ip2addr(int af, const void *inaddr, const char *hostname, int port); - -struct Curl_addrinfo *Curl_str2addr(char *dotted, int port); +bool Curl_is_ipaddr(const char *address); +CURLcode Curl_str2addr(const char *dotted, int port, struct Curl_addrinfo **); #ifdef USE_UNIX_SOCKETS struct Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, @@ -87,23 +82,23 @@ struct Curl_addrinfo *Curl_unix2addr(const char *path, bool *longpath, #endif #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) && \ - defined(HAVE_FREEADDRINFO) -void -curl_dbg_freeaddrinfo(struct addrinfo *freethis, int line, const char *source); + defined(HAVE_FREEADDRINFO) +void curl_dbg_freeaddrinfo(struct addrinfo *freethis, int line, + const char *source); #endif #if defined(CURLDEBUG) && defined(HAVE_GETADDRINFO) -int -curl_dbg_getaddrinfo(const char *hostname, const char *service, - const struct addrinfo *hints, struct addrinfo **result, - int line, const char *source); +int curl_dbg_getaddrinfo(const char *hostname, const char *service, + const struct addrinfo *hints, + struct addrinfo **result, int line, + const char *source); #endif #ifdef HAVE_GETADDRINFO #ifdef USE_RESOLVE_ON_IPS void Curl_addrinfo_set_port(struct Curl_addrinfo *addrinfo, int port); #else -#define Curl_addrinfo_set_port(x,y) +#define Curl_addrinfo_set_port(x, y) #endif #endif diff --git a/lib/curl_config.h.cmake b/lib/curl_config-cmake.h.in similarity index 97% rename from lib/curl_config.h.cmake rename to lib/curl_config-cmake.h.in index 1fabc24c182f..d8d9d7ecbe58 100644 --- a/lib/curl_config.h.cmake +++ b/lib/curl_config-cmake.h.in @@ -151,7 +151,7 @@ /* disabled WebSocket */ #cmakedefine CURL_DISABLE_WEBSOCKETS 1 -/* disables use of socketpair for curl_multi_poll */ +/* disables use of socketpair for curl_multi_poll() */ #cmakedefine CURL_DISABLE_SOCKETPAIR 1 /* disables TELNET */ @@ -160,6 +160,9 @@ /* disables TFTP */ #cmakedefine CURL_DISABLE_TFTP 1 +/* disables curl_easy_setopt()/curl_easy_getinfo() type checking */ +#cmakedefine CURL_DISABLE_TYPECHECK 1 + /* disables verbose strings */ #cmakedefine CURL_DISABLE_VERBOSE_STRINGS 1 @@ -388,6 +391,9 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_LOCALE_H 1 +/* Define to 1 if you have a working localtime_r function. */ +#cmakedefine HAVE_LOCALTIME_R 1 + /* Define to 1 if the compiler supports the 'long long' data type. */ #cmakedefine HAVE_LONGLONG 1 @@ -673,6 +679,9 @@ ${SIZEOF_TIME_T_CODE} /* if mbedTLS is enabled */ #cmakedefine USE_MBEDTLS 1 +/* if mbedTLS <4 has the mbedtls_des_crypt_ecb function. */ +#cmakedefine HAVE_MBEDTLS_DES_CRYPT_ECB 1 + /* if Rustls is enabled */ #cmakedefine USE_RUSTLS 1 @@ -724,6 +733,9 @@ ${SIZEOF_TIME_T_CODE} /* Define to 1 if you have the header file. */ #cmakedefine HAVE_UV_H 1 +/* if libbacktrace is in use */ +#cmakedefine USE_BACKTRACE 1 + /* Define to 1 if you do not want the OpenSSL configuration to be loaded automatically */ #cmakedefine CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG 1 @@ -752,9 +764,6 @@ ${SIZEOF_TIME_T_CODE} /* if Unix domain sockets are enabled */ #cmakedefine USE_UNIX_SOCKETS 1 -/* Define to 1 if you are building a Windows target with large file support. */ -#cmakedefine USE_WIN32_LARGE_FILES 1 - /* to enable SSPI support */ #cmakedefine USE_WINDOWS_SSPI 1 @@ -801,7 +810,10 @@ ${SIZEOF_TIME_T_CODE} #cmakedefine USE_ECH 1 /* Define to 1 if you have the wolfSSL_CTX_GenerateEchConfig function. */ -#cmakedefine HAVE_WOLFSSL_CTX_GENERATEECHCONFIG +#cmakedefine HAVE_WOLFSSL_CTX_GENERATEECHCONFIG 1 /* Define to 1 if you have the SSL_set1_ech_config_list function. */ -#cmakedefine HAVE_SSL_SET1_ECH_CONFIG_LIST +#cmakedefine HAVE_SSL_SET1_ECH_CONFIG_LIST 1 + +/* Define to 1 if OpenSSL has the DES_ecb_encrypt function. */ +#cmakedefine HAVE_DES_ECB_ENCRYPT 1 diff --git a/lib/curl_ctype.h b/lib/curl_ctype.h index 48c3c37c359c..153a8f9c6cdc 100644 --- a/lib/curl_ctype.h +++ b/lib/curl_ctype.h @@ -25,17 +25,17 @@ ***************************************************************************/ #define ISLOWHEXALHA(x) (((x) >= 'a') && ((x) <= 'f')) -#define ISUPHEXALHA(x) (((x) >= 'A') && ((x) <= 'F')) +#define ISUPHEXALHA(x) (((x) >= 'A') && ((x) <= 'F')) #define ISLOWCNTRL(x) ((unsigned char)(x) <= 0x1f) -#define IS7F(x) ((x) == 0x7f) +#define IS7F(x) ((x) == 0x7f) #define ISLOWPRINT(x) (((x) >= 9) && ((x) <= 0x0d)) #define ISPRINT(x) (ISLOWPRINT(x) || (((x) >= ' ') && ((x) <= 0x7e))) #define ISGRAPH(x) (ISLOWPRINT(x) || (((x) > ' ') && ((x) <= 0x7e))) -#define ISCNTRL(x) (ISLOWCNTRL(x) || IS7F(x)) -#define ISALPHA(x) (ISLOWER(x) || ISUPPER(x)) +#define ISCNTRL(x) (ISLOWCNTRL(x) || IS7F(x)) +#define ISALPHA(x) (ISLOWER(x) || ISUPPER(x)) #define ISXDIGIT(x) (ISDIGIT(x) || ISLOWHEXALHA(x) || ISUPHEXALHA(x)) #define ISODIGIT(x) (((x) >= '0') && ((x) <= '7')) #define ISALNUM(x) (ISDIGIT(x) || ISLOWER(x) || ISUPPER(x)) diff --git a/lib/curl_des.c b/lib/curl_des.c deleted file mode 100644 index a202dd3fe4a5..000000000000 --- a/lib/curl_des.c +++ /dev/null @@ -1,68 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) Steve Holme, . - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at https://curl.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the 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_CURL_NTLM_CORE) && \ - (defined(USE_GNUTLS) || \ - defined(USE_OS400CRYPTO) || \ - defined(USE_WIN32_CRYPTO)) - -#include "curl_des.h" - -/* - * Curl_des_set_odd_parity() - * - * This is used to apply odd parity to the given byte array. It is typically - * used by when a cryptography engine does not have its own version. - * - * The function is a port of the Java based oddParity() function over at: - * - * https://davenport.sourceforge.net/ntlm.html - * - * Parameters: - * - * bytes [in/out] - The data whose parity bits are to be adjusted for - * odd parity. - * len [out] - The length of the data. - */ -void Curl_des_set_odd_parity(unsigned char *bytes, size_t len) -{ - size_t i; - - for(i = 0; i < len; i++) { - unsigned char b = bytes[i]; - - bool needs_parity = (((b >> 7) ^ (b >> 6) ^ (b >> 5) ^ - (b >> 4) ^ (b >> 3) ^ (b >> 2) ^ - (b >> 1)) & 0x01) == 0; - - if(needs_parity) - bytes[i] |= 0x01; - else - bytes[i] &= 0xfe; - } -} - -#endif diff --git a/lib/curl_des.h b/lib/curl_des.h deleted file mode 100644 index c50aaf45b176..000000000000 --- a/lib/curl_des.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef HEADER_CURL_DES_H -#define HEADER_CURL_DES_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) Steve Holme, . - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at https://curl.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the 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_CURL_NTLM_CORE) && \ - (defined(USE_GNUTLS) || \ - defined(USE_OS400CRYPTO) || \ - defined(USE_WIN32_CRYPTO)) - -/* Applies odd parity to the given byte array */ -void Curl_des_set_odd_parity(unsigned char *bytes, size_t length); - -#endif - -#endif /* HEADER_CURL_DES_H */ diff --git a/lib/curl_fnmatch.c b/lib/curl_fnmatch.c index 66b9739f3c03..d61e7d43bc50 100644 --- a/lib/curl_fnmatch.c +++ b/lib/curl_fnmatch.c @@ -24,13 +24,8 @@ #include "curl_setup.h" #ifndef CURL_DISABLE_FTP -#include #include "curl_fnmatch.h" -#include "curl_memory.h" - -/* The last #include file should be: */ -#include "memdebug.h" #ifndef HAVE_FNMATCH @@ -243,7 +238,7 @@ static int setcharset(const unsigned char **p, unsigned char *charset) case CURLFNM_SCHS_RIGHTBRLEFTBR: if(c == ']') return SETCHARSET_OK; - state = CURLFNM_SCHS_DEFAULT; + state = CURLFNM_SCHS_DEFAULT; charset[c] = 1; (*p)++; break; diff --git a/lib/curl_fopen.c b/lib/curl_fopen.c index c41cff21cde9..383b307e2120 100644 --- a/lib/curl_fopen.c +++ b/lib/curl_fopen.c @@ -31,10 +31,6 @@ #include "rand.h" #include "curl_fopen.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - /* The dirslash() function breaks a null-terminated pathname string into directory and filename components then returns the directory component up @@ -66,10 +62,10 @@ static char *dirslash(const char *path) n = strlen(path); if(n) { /* find the rightmost path separator, if any */ - while(n && !IS_SEP(path[n-1])) + while(n && !IS_SEP(path[n - 1])) --n; /* skip over all the path separators, if any */ - while(n && IS_SEP(path[n-1])) + while(n && IS_SEP(path[n - 1])) --n; } if(curlx_dyn_addn(&out, path, n)) @@ -93,25 +89,22 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename, CURLcode result = CURLE_WRITE_ERROR; unsigned char randbuf[41]; char *tempstore = NULL; +#ifndef _WIN32 struct_stat sb; +#endif int fd = -1; char *dir = NULL; *tempname = NULL; +#ifndef _WIN32 *fh = curlx_fopen(filename, FOPEN_WRITETEXT); if(!*fh) goto fail; - if( -#ifdef UNDER_CE - /* !checksrc! disable BANNEDFUNC 1 */ - stat(filename, &sb) == -1 -#else - fstat(fileno(*fh), &sb) == -1 -#endif - || !S_ISREG(sb.st_mode)) { + if(fstat(fileno(*fh), &sb) == -1 || !S_ISREG(sb.st_mode)) { return CURLE_OK; } curlx_fclose(*fh); +#endif *fh = NULL; result = Curl_rand_alnum(data, randbuf, sizeof(randbuf)); @@ -123,7 +116,7 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename, /* The temp filename should not end up too long for the target file system */ tempstore = curl_maprintf("%s%s.tmp", dir, randbuf); - free(dir); + curlx_free(dir); } if(!tempstore) { @@ -132,13 +125,16 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename, } result = CURLE_WRITE_ERROR; -#if (defined(ANDROID) || defined(__ANDROID__)) && \ +#ifdef _WIN32 + fd = curlx_open(tempstore, O_WRONLY | O_CREAT | O_EXCL, + S_IREAD | S_IWRITE); +#elif (defined(ANDROID) || defined(__ANDROID__)) && \ (defined(__i386__) || defined(__arm__)) fd = curlx_open(tempstore, O_WRONLY | O_CREAT | O_EXCL, - (mode_t)(0600 | sb.st_mode)); + (mode_t)(S_IRUSR | S_IWUSR | sb.st_mode)); #else fd = curlx_open(tempstore, O_WRONLY | O_CREAT | O_EXCL, - 0600 | sb.st_mode); + S_IRUSR | S_IWUSR | sb.st_mode); #endif if(fd == -1) goto fail; @@ -156,7 +152,7 @@ CURLcode Curl_fopen(struct Curl_easy *data, const char *filename, unlink(tempstore); } - free(tempstore); + curlx_free(tempstore); return result; } diff --git a/lib/curl_get_line.c b/lib/curl_get_line.c index 4b1c6c3e0970..5e553f4d31de 100644 --- a/lib/curl_get_line.c +++ b/lib/curl_get_line.c @@ -28,67 +28,43 @@ !defined(CURL_DISABLE_HSTS) || !defined(CURL_DISABLE_NETRC) #include "curl_get_line.h" -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" -static int appendnl(struct dynbuf *buf) -{ - CURLcode result = curlx_dyn_addn(buf, "\n", 1); - if(result) - /* too long line or out of memory */ - return 0; /* error */ - return 1; /* all good */ -} +#define appendnl(b) curlx_dyn_addn(buf, "\n", 1) /* - * Curl_get_line() makes sure to only return complete whole lines that end - * newlines. + * Curl_get_line() returns only complete whole lines that end with newline. + * When 'eof' is set TRUE, the last line has been read. */ -int Curl_get_line(struct dynbuf *buf, FILE *input) +CURLcode Curl_get_line(struct dynbuf *buf, FILE *input, bool *eof) { CURLcode result; char buffer[128]; curlx_dyn_reset(buf); while(1) { - char *b = fgets(buffer, sizeof(buffer), input); size_t rlen; + char *b = fgets(buffer, sizeof(buffer), input); - if(b) { - rlen = strlen(b); - - if(!rlen) - break; + *eof = feof(input); + rlen = b ? strlen(b) : 0; + if(rlen) { result = curlx_dyn_addn(buf, b, rlen); if(result) /* too long line or out of memory */ - return 0; /* error */ - - else if(b[rlen-1] == '\n') - /* end of the line */ - return 1; /* all good */ - - else if(feof(input)) - /* append a newline */ - return appendnl(buf); - } - else { - rlen = curlx_dyn_len(buf); - if(rlen) { - b = curlx_dyn_ptr(buf); - - if(b[rlen-1] != '\n') - /* append a newline */ - return appendnl(buf); - - return 1; /* all good */ - } - else - break; + return result; } + /* now check the full line */ + rlen = curlx_dyn_len(buf); + b = curlx_dyn_ptr(buf); + if(rlen && (b[rlen - 1] == '\n')) + /* LF at end of the line */ + return CURLE_OK; /* all good */ + if(*eof) + /* append a newline */ + return appendnl(buf); + /* otherwise get next line to append */ } - return 0; + /* UNREACHABLE */ } #endif /* if not disabled */ diff --git a/lib/curl_get_line.h b/lib/curl_get_line.h index d4877123f261..176d5f7a30e3 100644 --- a/lib/curl_get_line.h +++ b/lib/curl_get_line.h @@ -27,6 +27,6 @@ #include "curlx/dynbuf.h" /* Curl_get_line() returns complete lines that end with a newline. */ -int Curl_get_line(struct dynbuf *buf, FILE *input); +CURLcode Curl_get_line(struct dynbuf *buf, FILE *input, bool *eof); #endif /* HEADER_CURL_GET_LINE_H */ diff --git a/lib/curl_gethostname.c b/lib/curl_gethostname.c index c3fa864effca..4d772cb49153 100644 --- a/lib/curl_gethostname.c +++ b/lib/curl_gethostname.c @@ -23,8 +23,8 @@ ***************************************************************************/ #include "curl_setup.h" - #include "curl_gethostname.h" +#include "curlx/strcopy.h" /* * Curl_gethostname() is a wrapper around gethostname() which allows @@ -60,9 +60,9 @@ int Curl_gethostname(char * const name, GETHOSTNAME_TYPE_ARG2 namelen) const char *force_hostname = getenv("CURL_GETHOSTNAME"); if(force_hostname) { if(strlen(force_hostname) < (size_t)namelen) - strcpy(name, force_hostname); + curlx_strcopy(name, namelen, force_hostname, strlen(force_hostname)); else - return 1; /* can't do it */ + return 1; /* cannot do it */ err = 0; } else { @@ -93,5 +93,4 @@ int Curl_gethostname(char * const name, GETHOSTNAME_TYPE_ARG2 namelen) return 0; #endif - } diff --git a/lib/curl_gssapi.c b/lib/curl_gssapi.c index 42ccaa3e2962..2145b42686d3 100644 --- a/lib/curl_gssapi.c +++ b/lib/curl_gssapi.c @@ -27,11 +27,28 @@ #ifdef HAVE_GSSAPI #include "curl_gssapi.h" -#include "sendf.h" +#include "curl_trc.h" +#include "curlx/strcopy.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" +#ifdef DEBUGBUILD +#if defined(HAVE_GSSGNU) || !defined(_WIN32) +#define Curl_gss_alloc malloc /* freed via the GSS API gss_release_buffer() */ +#define Curl_gss_free free /* pair of the above */ +#define CURL_GSS_STUB +/* For correctness this would be required for all platforms, not only Windows, + but, as of v1.22.1, MIT Kerberos uses a special allocator only for Windows, + and the availability of 'gssapi/gssapi_alloc.h' is difficult to detect, + because GSS headers are not versioned, and there is also no other macro to + indicate 1.18+ vs. previous versions. On Windows we can use 'GSS_S_BAD_MIC'. + */ +#elif defined(_WIN32) && defined(GSS_S_BAD_MIC) /* MIT Kerberos 1.15+ */ +/* MIT Kerberos 1.10+ (Windows), 1.18+ (all platforms), missing from GNU GSS */ +#include +#define Curl_gss_alloc gssalloc_malloc +#define Curl_gss_free gssalloc_free +#define CURL_GSS_STUB +#endif +#endif /* DEBUGBUILD */ #ifdef __GNUC__ #define CURL_ALIGN8 __attribute__((aligned(8))) @@ -51,7 +68,7 @@ gss_OID_desc Curl_krb5_mech_oid CURL_ALIGN8 = { 9, CURL_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02") }; -#ifdef DEBUGBUILD +#ifdef CURL_GSS_STUB enum min_err_code { STUB_GSS_OK = 0, STUB_GSS_NO_MEMORY, @@ -138,7 +155,7 @@ stub_gss_init_sec_context(OM_uint32 *min, } /* Server response, either D (RA==) or C (Qw==) */ - if(((char *) input_token->value)[0] == 'D') { + if(((char *)input_token->value)[0] == 'D') { /* Done */ switch(ctx->sent) { case STUB_GSS_KRB5: @@ -154,7 +171,7 @@ stub_gss_init_sec_context(OM_uint32 *min, } } - if(((char *) input_token->value)[0] != 'C') { + if(((char *)input_token->value)[0] != 'C') { /* We only support Done or Continue */ *min = STUB_GSS_SERVER_ERR; return GSS_S_FAILURE; @@ -186,7 +203,7 @@ stub_gss_init_sec_context(OM_uint32 *min, return GSS_S_FAILURE; } - ctx = calloc(1, sizeof(*ctx)); + ctx = curlx_calloc(1, sizeof(*ctx)); if(!ctx) { *min = STUB_GSS_NO_MEMORY; return GSS_S_FAILURE; @@ -203,20 +220,18 @@ stub_gss_init_sec_context(OM_uint32 *min, else if(ctx->have_ntlm) ctx->sent = STUB_GSS_NTLM1; else { - free(ctx); + curlx_free(ctx); *min = STUB_GSS_NO_MECH; return GSS_S_FAILURE; } - strcpy(ctx->creds, creds); + curlx_strcopy(ctx->creds, sizeof(ctx->creds), creds, strlen(creds)); ctx->flags = req_flags; } - /* To avoid memdebug macro replacement, wrap the name in parentheses to call - the original version. It is freed via the GSS API gss_release_buffer(). */ - token = (malloc)(length); + token = Curl_gss_alloc(length); if(!token) { - free(ctx); + curlx_free(ctx); *min = STUB_GSS_NO_MEMORY; return GSS_S_FAILURE; } @@ -229,15 +244,15 @@ stub_gss_init_sec_context(OM_uint32 *min, major_status = gss_display_name(&minor_status, target_name, &target_desc, &name_type); if(GSS_ERROR(major_status)) { - (free)(token); - free(ctx); + Curl_gss_free(token); + curlx_free(ctx); *min = STUB_GSS_NO_MEMORY; return GSS_S_FAILURE; } if(strlen(creds) + target_desc.length + 5 >= sizeof(ctx->creds)) { - (free)(token); - free(ctx); + Curl_gss_free(token); + curlx_free(ctx); *min = STUB_GSS_NO_MEMORY; return GSS_S_FAILURE; } @@ -252,8 +267,8 @@ stub_gss_init_sec_context(OM_uint32 *min, } if(used >= length) { - (free)(token); - free(ctx); + Curl_gss_free(token); + curlx_free(ctx); *min = STUB_GSS_NO_MEMORY; return GSS_S_FAILURE; } @@ -288,13 +303,13 @@ stub_gss_delete_sec_context(OM_uint32 *min, return GSS_S_FAILURE; } - free(*context); + curlx_free(*context); *context = NULL; *min = 0; return GSS_S_COMPLETE; } -#endif /* DEBUGBUILD */ +#endif /* CURL_GSS_STUB */ OM_uint32 Curl_gss_init_sec_context(struct Curl_easy *data, OM_uint32 *minor_status, @@ -324,7 +339,7 @@ OM_uint32 Curl_gss_init_sec_context(struct Curl_easy *data, if(data->set.gssapi_delegation & CURLGSSAPI_DELEGATION_FLAG) req_flags |= GSS_C_DELEG_FLAG; -#ifdef DEBUGBUILD +#ifdef CURL_GSS_STUB if(getenv("CURL_STUB_GSS_CREDS")) return stub_gss_init_sec_context(minor_status, GSS_C_NO_CREDENTIAL, /* cred_handle */ @@ -339,7 +354,7 @@ OM_uint32 Curl_gss_init_sec_context(struct Curl_easy *data, output_token, ret_flags, NULL /* time_rec */); -#endif /* DEBUGBUILD */ +#endif /* CURL_GSS_STUB */ return gss_init_sec_context(minor_status, GSS_C_NO_CREDENTIAL, /* cred_handle */ @@ -360,19 +375,20 @@ OM_uint32 Curl_gss_delete_sec_context(OM_uint32 *min, gss_ctx_id_t *context, gss_buffer_t output_token) { -#ifdef DEBUGBUILD +#ifdef CURL_GSS_STUB if(getenv("CURL_STUB_GSS_CREDS")) return stub_gss_delete_sec_context(min, (struct stub_gss_ctx_id_t_desc **)context, output_token); -#endif /* DEBUGBUILD */ +#endif /* CURL_GSS_STUB */ return gss_delete_sec_context(min, context, output_token); } #define GSS_LOG_BUFFER_LEN 1024 static size_t display_gss_error(OM_uint32 status, int type, - char *buf, size_t len) { + char *buf, size_t len) +{ OM_uint32 maj_stat; OM_uint32 min_stat; OM_uint32 msg_ctx = 0; @@ -413,7 +429,7 @@ static size_t display_gss_error(OM_uint32 status, int type, void Curl_gss_log_error(struct Curl_easy *data, const char *prefix, OM_uint32 major, OM_uint32 minor) { - char buf[GSS_LOG_BUFFER_LEN]; + char buf[GSS_LOG_BUFFER_LEN] = ""; size_t len = 0; if(major != GSS_S_FAILURE) diff --git a/lib/curl_gssapi.h b/lib/curl_gssapi.h index 6df7e059d325..d4fbf5c2403c 100644 --- a/lib/curl_gssapi.h +++ b/lib/curl_gssapi.h @@ -25,6 +25,7 @@ ***************************************************************************/ #include "curl_setup.h" + #include "urldata.h" #ifdef HAVE_GSSAPI diff --git a/lib/curl_hmac.h b/lib/curl_hmac.h index 9675c6c54259..4759ff6ec662 100644 --- a/lib/curl_hmac.h +++ b/lib/curl_hmac.h @@ -28,8 +28,6 @@ !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) || \ defined(USE_LIBSSH2) || defined(USE_SSL) -#include - #define HMAC_MD5_LENGTH 16 typedef CURLcode (*HMAC_hinit)(void *context); @@ -48,7 +46,6 @@ struct HMAC_params { unsigned int resultlen; /* Result length (bytes). */ }; - /* HMAC computation context. */ struct HMAC_context { const struct HMAC_params *hash; /* Hash function definition. */ @@ -56,7 +53,6 @@ struct HMAC_context { void *hashctxt2; /* Hash function context 2. */ }; - /* Prototypes. */ struct HMAC_context *Curl_HMAC_init(const struct HMAC_params *hashparams, const unsigned char *key, diff --git a/lib/curl_ldap.h b/lib/curl_ldap.h index 8a1d807ed92b..5ef32a5a30ae 100644 --- a/lib/curl_ldap.h +++ b/lib/curl_ldap.h @@ -26,11 +26,12 @@ #ifndef CURL_DISABLE_LDAP extern const struct Curl_handler Curl_handler_ldap; -#if !defined(CURL_DISABLE_LDAPS) && \ - ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ - (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) +#if !defined(CURL_DISABLE_LDAPS) && \ + ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ + (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) extern const struct Curl_handler Curl_handler_ldaps; #endif +void Curl_ldap_version(char *buf, size_t bufsz); #endif #endif /* HEADER_CURL_LDAP_H */ diff --git a/lib/curl_md4.h b/lib/curl_md4.h index f103d38b41b5..9d4a12ed3d27 100644 --- a/lib/curl_md4.h +++ b/lib/curl_md4.h @@ -25,7 +25,6 @@ ***************************************************************************/ #include "curl_setup.h" -#include #ifdef USE_CURL_NTLM_CORE diff --git a/lib/curl_memory.h b/lib/curl_memory.h deleted file mode 100644 index 7793bb63a389..000000000000 --- a/lib/curl_memory.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef HEADER_CURL_MEMORY_H -#define HEADER_CURL_MEMORY_H -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at https://curl.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - * SPDX-License-Identifier: curl - * - ***************************************************************************/ - -/* - * Nasty internal details ahead... - * - * File curl_memory.h must be included by _all_ *.c source files - * that use memory related functions strdup, malloc, calloc, realloc - * or free, and given source file is used to build libcurl library. - * It should be included immediately before memdebug.h as the last files - * included to avoid undesired interaction with other memory function - * headers in dependent libraries. - * - * There is nearly no exception to above rule. All libcurl source - * files in 'lib' subdirectory as well as those living deep inside - * 'packages' subdirectories and linked together in order to build - * libcurl library shall follow it. - * - * File lib/strdup.c is an exception, given that it provides a strdup - * clone implementation while using malloc. Extra care needed inside - * this one. - * - * The need for curl_memory.h inclusion is due to libcurl's feature - * of allowing library user to provide memory replacement functions, - * memory callbacks, at runtime with curl_global_init_mem() - * - * Any *.c source file used to build libcurl library that does not - * include curl_memory.h and uses any memory function of the five - * mentioned above will compile without any indication, but it will - * trigger weird memory related issues at runtime. - * - */ - -#ifndef CURLDEBUG - -/* - * libcurl's 'memory tracking' system defines strdup, malloc, calloc, - * realloc and free, along with others, in memdebug.h in a different - * way although still using memory callbacks forward declared above. - * When using the 'memory tracking' system (CURLDEBUG defined) we do - * not define here the five memory functions given that definitions - * from memdebug.h are the ones that shall be used. - */ - -#undef strdup -#define strdup(ptr) Curl_cstrdup(ptr) -#undef malloc -#define malloc(size) Curl_cmalloc(size) -#undef calloc -#define calloc(nbelem,size) Curl_ccalloc(nbelem, size) -#undef realloc -#define realloc(ptr,size) Curl_crealloc(ptr, size) -#undef free -#define free(ptr) Curl_cfree(ptr) - -#ifdef _WIN32 -#undef Curl_tcsdup -#ifdef UNICODE -#define Curl_tcsdup(ptr) Curl_wcsdup(ptr) -#else -#define Curl_tcsdup(ptr) Curl_cstrdup(ptr) -#endif -#endif /* _WIN32 */ - -#endif /* CURLDEBUG */ -#endif /* HEADER_CURL_MEMORY_H */ diff --git a/lib/curl_memrchr.c b/lib/curl_memrchr.c index 5b6a39c022cc..27f5fc01ba10 100644 --- a/lib/curl_memrchr.c +++ b/lib/curl_memrchr.c @@ -24,13 +24,7 @@ #include "curl_setup.h" -#include - #include "curl_memrchr.h" -#include "curl_memory.h" - -/* The last #include file should be: */ -#include "memdebug.h" #ifndef HAVE_MEMRCHR /* @@ -41,9 +35,7 @@ * backwards from the end of the n bytes pointed to by s instead of forward * from the beginning. */ - -void * -Curl_memrchr(const void *s, int c, size_t n) +void *Curl_memrchr(const void *s, int c, size_t n) { if(n > 0) { const unsigned char *p = s; diff --git a/lib/curl_memrchr.h b/lib/curl_memrchr.h index 3c7dda96ac98..2ee65f3c0ba0 100644 --- a/lib/curl_memrchr.h +++ b/lib/curl_memrchr.h @@ -28,14 +28,13 @@ #ifdef HAVE_MEMRCHR -#include #ifdef HAVE_STRINGS_H # include #endif #else /* HAVE_MEMRCHR */ void *Curl_memrchr(const void *s, int c, size_t n); -#define memrchr(x,y,z) Curl_memrchr((x),(y),(z)) +#define memrchr(x, y, z) Curl_memrchr(x, y, z) #endif /* HAVE_MEMRCHR */ diff --git a/lib/curl_ntlm_core.c b/lib/curl_ntlm_core.c index cf0e4dc28832..36778ecae7c9 100644 --- a/lib/curl_ntlm_core.c +++ b/lib/curl_ntlm_core.c @@ -38,10 +38,9 @@ 1. USE_OPENSSL 2. USE_WOLFSSL 3. USE_GNUTLS - 4. - - 5. USE_MBEDTLS - 6. USE_OS400CRYPTO - 7. USE_WIN32_CRYPTO + 4. USE_MBEDTLS + 5. USE_OS400CRYPTO + 6. USE_WIN32_CRYPTO This ensures that: - the same SSL branch gets activated throughout this source @@ -51,42 +50,40 @@ in NTLM type-3 messages. */ -#ifdef USE_OPENSSL - #include - #if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_DEPRECATED_3_0) - #define USE_OPENSSL_DES - #endif -#elif defined(USE_WOLFSSL) - #include - #ifndef NO_DES3 - #define USE_OPENSSL_DES - #endif +#ifdef USE_MBEDTLS +#include +#if MBEDTLS_VERSION_NUMBER < 0x03020000 +#error "mbedTLS 3.2.0 or later required" +#endif +#endif + +#if defined(USE_OPENSSL) && defined(HAVE_DES_ECB_ENCRYPT) + #define USE_OPENSSL_DES +#elif defined(USE_WOLFSSL) && defined(HAVE_WOLFSSL_DES_ECB_ENCRYPT) + #define USE_OPENSSL_DES +#elif defined(USE_MBEDTLS) && defined(HAVE_MBEDTLS_DES_CRYPT_ECB) + #define USE_MBEDTLS_DES #endif #ifdef USE_OPENSSL_DES #ifdef USE_OPENSSL # include -# include -# include -# include # ifdef OPENSSL_IS_AWSLC /* for versions 1.2.0 to 1.30.1 */ # define DES_set_key_unchecked (void)DES_set_key # endif # define DESKEY(x) &x #else +# include # include -# include -# include -# include # ifdef OPENSSL_COEXIST -# define DES_key_schedule WOLFSSL_DES_key_schedule -# define DES_cblock WOLFSSL_DES_cblock -# define DES_set_odd_parity wolfSSL_DES_set_odd_parity -# define DES_set_key wolfSSL_DES_set_key +# define DES_key_schedule WOLFSSL_DES_key_schedule +# define DES_cblock WOLFSSL_DES_cblock +# define DES_set_odd_parity wolfSSL_DES_set_odd_parity +# define DES_set_key wolfSSL_DES_set_key # define DES_set_key_unchecked wolfSSL_DES_set_key_unchecked -# define DES_ecb_encrypt wolfSSL_DES_ecb_encrypt -# define DESKEY(x) ((WOLFSSL_DES_key_schedule *)(x)) +# define DES_ecb_encrypt wolfSSL_DES_ecb_encrypt +# define DESKEY(x) ((WOLFSSL_DES_key_schedule *)(x)) # else # define DESKEY(x) &x # endif @@ -96,18 +93,20 @@ #elif defined(USE_GNUTLS) # include +# define USE_CURL_DES_SET_ODD_PARITY -#elif defined(USE_MBEDTLS) +#elif defined(USE_MBEDTLS_DES) # include #elif defined(USE_OS400CRYPTO) # include "cipher.mih" /* mih/cipher */ +# define USE_CURL_DES_SET_ODD_PARITY #elif defined(USE_WIN32_CRYPTO) # include +# define USE_CURL_DES_SET_ODD_PARITY #else # error "cannot compile NTLM support without a crypto library with DES." -# define CURL_NTLM_NOT_SUPPORTED #endif #include "urldata.h" @@ -115,19 +114,50 @@ #include "curl_ntlm_core.h" #include "curl_md5.h" #include "curl_hmac.h" -#include "curlx/warnless.h" -#include "curl_endian.h" -#include "curl_des.h" #include "curl_md4.h" +#include "vauth/vauth.h" + +#ifdef USE_CURL_DES_SET_ODD_PARITY +/* + * curl_des_set_odd_parity() + * + * Copyright (C) Steve Holme, + * + * This is used to apply odd parity to the given byte array. It is typically + * used by when a cryptography engine does not have its own version. + * + * The function is a port of the Java based oddParity() function over at: + * + * https://davenport.sourceforge.net/ntlm.html + * + * Parameters: + * + * bytes [in/out] - The data whose parity bits are to be adjusted for + * odd parity. + * len [out] - The length of the data. + */ +static void curl_des_set_odd_parity(unsigned char *bytes, size_t len) +{ + size_t i; + + for(i = 0; i < len; i++) { + unsigned char b = bytes[i]; + + bool needs_parity = (((b >> 7) ^ (b >> 6) ^ (b >> 5) ^ + (b >> 4) ^ (b >> 3) ^ (b >> 2) ^ + (b >> 1)) & 0x01) == 0; -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" + if(needs_parity) + bytes[i] |= 0x01; + else + bytes[i] &= 0xfe; + } +} +#endif /* USE_CURL_DES_SET_ODD_PARITY */ -#ifndef CURL_NTLM_NOT_SUPPORTED /* -* Turns a 56-bit key into being 64-bit wide. -*/ + * Turns a 56-bit key into being 64-bit wide. + */ static void extend_key_56_to_64(const unsigned char *key_56, char *key) { key[0] = (char)key_56[0]; @@ -139,7 +169,6 @@ static void extend_key_56_to_64(const unsigned char *key_56, char *key) key[6] = (char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6)); key[7] = (char) ((key_56[6] << 1) & 0xFF); } -#endif #ifdef USE_OPENSSL_DES /* @@ -152,7 +181,7 @@ static void setup_des_key(const unsigned char *key_56, DES_cblock key; /* Expand the 56-bit key to 64 bits */ - extend_key_56_to_64(key_56, (char *) &key); + extend_key_56_to_64(key_56, (char *)&key); /* Set the key parity to odd */ DES_set_odd_parity(&key); @@ -163,8 +192,7 @@ static void setup_des_key(const unsigned char *key_56, #elif defined(USE_GNUTLS) -static void setup_des_key(const unsigned char *key_56, - struct des_ctx *des) +static void setup_des_key(const unsigned char *key_56, struct des_ctx *des) { char key[8]; @@ -172,13 +200,13 @@ static void setup_des_key(const unsigned char *key_56, extend_key_56_to_64(key_56, key); /* Set the key parity to odd */ - Curl_des_set_odd_parity((unsigned char *) key, sizeof(key)); + curl_des_set_odd_parity((unsigned char *)key, sizeof(key)); /* Set the key */ - des_set_key(des, (const uint8_t *) key); + des_set_key(des, (const uint8_t *)key); } -#elif defined(USE_MBEDTLS) +#elif defined(USE_MBEDTLS_DES) static bool encrypt_des(const unsigned char *in, unsigned char *out, const unsigned char *key_56) @@ -190,11 +218,11 @@ static bool encrypt_des(const unsigned char *in, unsigned char *out, extend_key_56_to_64(key_56, key); /* Set the key parity to odd */ - mbedtls_des_key_set_parity((unsigned char *) key); + mbedtls_des_key_set_parity((unsigned char *)key); /* Perform the encryption */ mbedtls_des_init(&ctx); - mbedtls_des_setkey_enc(&ctx, (unsigned char *) key); + mbedtls_des_setkey_enc(&ctx, (unsigned char *)key); return mbedtls_des_crypt_ecb(&ctx, in, out) == 0; } @@ -214,10 +242,10 @@ static bool encrypt_des(const unsigned char *in, unsigned char *out, extend_key_56_to_64(key_56, ctl.Crypto_Key); /* Set the key parity to odd */ - Curl_des_set_odd_parity((unsigned char *) ctl.Crypto_Key, ctl.Data_Len); + curl_des_set_odd_parity((unsigned char *)ctl.Crypto_Key, ctl.Data_Len); /* Perform the encryption */ - _CIPHER((_SPCPTR *) &out, &ctl, (_SPCPTR *) &in); + _CIPHER((_SPCPTR *)&out, &ctl, (_SPCPTR *)&in); return TRUE; } @@ -252,10 +280,10 @@ static bool encrypt_des(const unsigned char *in, unsigned char *out, extend_key_56_to_64(key_56, blob.key); /* Set the key parity to odd */ - Curl_des_set_odd_parity((unsigned char *) blob.key, sizeof(blob.key)); + curl_des_set_odd_parity((unsigned char *)blob.key, sizeof(blob.key)); /* Import the key */ - if(!CryptImportKey(hprov, (BYTE *) &blob, sizeof(blob), 0, 0, &hkey)) { + if(!CryptImportKey(hprov, (BYTE *)&blob, sizeof(blob), 0, 0, &hkey)) { CryptReleaseContext(hprov, 0); return FALSE; @@ -274,11 +302,11 @@ static bool encrypt_des(const unsigned char *in, unsigned char *out, #endif /* USE_WIN32_CRYPTO */ - /* - * takes a 21 byte array and treats it as 3 56-bit DES keys. The - * 8 byte plaintext is encrypted with each key and the resulting 24 - * bytes are stored in the results array. - */ +/* + * takes a 21 byte array and treats it as 3 56-bit DES keys. The + * 8 byte plaintext is encrypted with each key and the resulting 24 + * bytes are stored in the results array. + */ void Curl_ntlm_core_lm_resp(const unsigned char *keys, const unsigned char *plaintext, unsigned char *results) @@ -287,16 +315,16 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys, DES_key_schedule ks; setup_des_key(keys, DESKEY(ks)); - DES_ecb_encrypt((DES_cblock*)CURL_UNCONST(plaintext), - (DES_cblock*)results, DESKEY(ks), DES_ENCRYPT); + DES_ecb_encrypt((DES_cblock *)CURL_UNCONST(plaintext), + (DES_cblock *)results, DESKEY(ks), DES_ENCRYPT); setup_des_key(keys + 7, DESKEY(ks)); - DES_ecb_encrypt((DES_cblock*)CURL_UNCONST(plaintext), - (DES_cblock*)(results + 8), DESKEY(ks), DES_ENCRYPT); + DES_ecb_encrypt((DES_cblock *)CURL_UNCONST(plaintext), + (DES_cblock *)(results + 8), DESKEY(ks), DES_ENCRYPT); setup_des_key(keys + 14, DESKEY(ks)); - DES_ecb_encrypt((DES_cblock*)CURL_UNCONST(plaintext), - (DES_cblock*)(results + 16), DESKEY(ks), DES_ENCRYPT); + DES_ecb_encrypt((DES_cblock *)CURL_UNCONST(plaintext), + (DES_cblock *)(results + 16), DESKEY(ks), DES_ENCRYPT); #elif defined(USE_GNUTLS) struct des_ctx des; setup_des_key(keys, &des); @@ -305,7 +333,7 @@ void Curl_ntlm_core_lm_resp(const unsigned char *keys, des_encrypt(&des, 8, results + 8, plaintext); setup_des_key(keys + 14, &des); des_encrypt(&des, 8, results + 16, plaintext); -#elif defined(USE_MBEDTLS) || defined(USE_OS400CRYPTO) || \ +#elif defined(USE_MBEDTLS_DES) || defined(USE_OS400CRYPTO) || \ defined(USE_WIN32_CRYPTO) encrypt_des(plaintext, results, keys); encrypt_des(plaintext, results + 8, keys + 7); @@ -324,11 +352,9 @@ CURLcode Curl_ntlm_core_mk_lm_hash(const char *password, unsigned char *lmbuffer /* 21 bytes */) { unsigned char pw[14]; -#ifndef 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); @@ -353,7 +379,7 @@ CURLcode Curl_ntlm_core_mk_lm_hash(const char *password, des_encrypt(&des, 8, lmbuffer, magic); setup_des_key(pw + 7, &des); des_encrypt(&des, 8, lmbuffer + 8, magic); -#elif defined(USE_MBEDTLS) || defined(USE_OS400CRYPTO) || \ +#elif defined(USE_MBEDTLS_DES) || defined(USE_OS400CRYPTO) || \ defined(USE_WIN32_CRYPTO) encrypt_des(magic, lmbuffer, pw); encrypt_des(magic, lmbuffer + 8, pw + 7); @@ -399,9 +425,9 @@ CURLcode Curl_ntlm_core_mk_nt_hash(const char *password, size_t len = strlen(password); unsigned char *pw; CURLcode result; - if(len > SIZE_MAX/2) /* avoid integer overflow */ + if(len > SIZE_MAX / 2) /* avoid integer overflow */ return CURLE_OUT_OF_MEMORY; - pw = len ? malloc(len * 2) : (unsigned char *)strdup(""); + pw = len ? curlx_malloc(len * 2) : (unsigned char *)curlx_strdup(""); if(!pw) return CURLE_OUT_OF_MEMORY; @@ -412,7 +438,7 @@ CURLcode Curl_ntlm_core_mk_nt_hash(const char *password, if(!result) memset(ntbuffer + 16, 0, 21 - 16); - free(pw); + curlx_free(pw); return result; } @@ -420,7 +446,7 @@ CURLcode Curl_ntlm_core_mk_nt_hash(const char *password, #ifndef USE_WINDOWS_SSPI #define NTLMv2_BLOB_SIGNATURE "\x01\x01\x00\x00" -#define NTLMv2_BLOB_LEN (44 -16 + ntlm->target_info_len + 4) +#define NTLMv2_BLOB_LEN (44 - 16 + ntlm->target_info_len + 4) /* Timestamp in tenths of a microsecond since January 1, 1601 00:00:00 UTC. */ struct ms_filetime { @@ -433,20 +459,20 @@ static void time2filetime(struct ms_filetime *ft, time_t t) { #if SIZEOF_TIME_T > 4 t = (t + (curl_off_t)11644473600) * 10000000; - ft->dwLowDateTime = (unsigned int) (t & 0xFFFFFFFF); - ft->dwHighDateTime = (unsigned int) (t >> 32); + ft->dwLowDateTime = (unsigned int)(t & 0xFFFFFFFF); + ft->dwHighDateTime = (unsigned int)(t >> 32); #else unsigned int r, s; unsigned int i; - ft->dwLowDateTime = (unsigned int)t & 0xFFFFFFFF; + ft->dwLowDateTime = (unsigned int)(t & 0xFFFFFFFF); ft->dwHighDateTime = 0; -# ifndef HAVE_TIME_T_UNSIGNED +#ifndef HAVE_TIME_T_UNSIGNED /* Extend sign if needed. */ if(ft->dwLowDateTime & 0x80000000) ft->dwHighDateTime = ~(unsigned int)0; -# endif +#endif /* Bias seconds to Jan 1, 1601. 134774 days = 11644473600 seconds = 0x2B6109100 */ @@ -489,7 +515,7 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen, return CURLE_OUT_OF_MEMORY; identity_len = (userlen + domlen) * 2; - identity = malloc(identity_len + 1); + identity = curlx_malloc(identity_len + 1); if(!identity) return CURLE_OUT_OF_MEMORY; @@ -499,7 +525,7 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen, result = Curl_hmacit(&Curl_HMAC_MD5, ntlmhash, 16, identity, identity_len, ntlmv2hash); - free(identity); + curlx_free(identity); return result; } @@ -527,20 +553,20 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, unsigned char **ntresp, unsigned int *ntresp_len) { -/* NTLMv2 response structure : ------------------------------------------------------------------------------- -0 HMAC MD5 16 bytes -------BLOB-------------------------------------------------------------------- -16 Signature 0x01010000 -20 Reserved long (0x00000000) -24 Timestamp LE, 64-bit signed value representing the number of - tenths of a microsecond since January 1, 1601. -32 Client Nonce 8 bytes -40 Unknown 4 bytes -44 Target Info N bytes (from the type-2 message) -44+N Unknown 4 bytes ------------------------------------------------------------------------------- -*/ + /* NTLMv2 response structure : + ----------------------------------------------------------------------------- + 0 HMAC MD5 16 bytes + ------BLOB------------------------------------------------------------------- + 16 Signature 0x01010000 + 20 Reserved long (0x00000000) + 24 Timestamp LE, 64-bit signed value representing the number of + tenths of a microsecond since January 1, 1601. + 32 Client Nonce 8 bytes + 40 Unknown 4 bytes + 44 Target Info N bytes (from the type-2 message) + 44+N Unknown 4 bytes + ----------------------------------------------------------------------------- + */ unsigned int len = 0; unsigned char *ptr = NULL; @@ -553,7 +579,7 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, #ifdef DEBUGBUILD char *force_timestamp = getenv("CURL_FORCETIME"); if(force_timestamp) - time2filetime(&tw, (time_t) 0); + time2filetime(&tw, (time_t)0); else #endif time2filetime(&tw, time(NULL)); @@ -562,7 +588,7 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, len = HMAC_MD5_LENGTH + NTLMv2_BLOB_LEN; /* Allocate the response */ - ptr = calloc(1, len); + ptr = curlx_calloc(1, len); if(!ptr) return CURLE_OUT_OF_MEMORY; @@ -586,7 +612,7 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, result = Curl_hmacit(&Curl_HMAC_MD5, ntlmv2hash, HMAC_MD5_LENGTH, ptr + 8, NTLMv2_BLOB_LEN + 8, hmac_output); if(result) { - free(ptr); + curlx_free(ptr); return result; } @@ -614,10 +640,10 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, * * Returns CURLE_OK on success. */ -CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash, - unsigned char *challenge_client, - unsigned char *challenge_server, - unsigned char *lmresp) +CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash, + unsigned char *challenge_client, + unsigned char *challenge_server, + unsigned char *lmresp) { unsigned char data[16]; unsigned char hmac_output[16]; diff --git a/lib/curl_ntlm_core.h b/lib/curl_ntlm_core.h index 584f4a17d508..0d2aa2186274 100644 --- a/lib/curl_ntlm_core.h +++ b/lib/curl_ntlm_core.h @@ -28,8 +28,6 @@ #ifdef USE_CURL_NTLM_CORE -#include "vauth/vauth.h" - struct ntlmdata; /* Helpers to generate function byte arguments in little endian order */ @@ -58,16 +56,16 @@ CURLcode Curl_ntlm_core_mk_ntlmv2_hash(const char *user, size_t userlen, unsigned char *ntlmhash, unsigned char *ntlmv2hash); -CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, - unsigned char *challenge_client, - struct ntlmdata *ntlm, - unsigned char **ntresp, - unsigned int *ntresp_len); +CURLcode Curl_ntlm_core_mk_ntlmv2_resp(unsigned char *ntlmv2hash, + unsigned char *challenge_client, + struct ntlmdata *ntlm, + unsigned char **ntresp, + unsigned int *ntresp_len); -CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash, - unsigned char *challenge_client, - unsigned char *challenge_server, - unsigned char *lmresp); +CURLcode Curl_ntlm_core_mk_lmv2_resp(unsigned char *ntlmv2hash, + unsigned char *challenge_client, + unsigned char *challenge_server, + unsigned char *lmresp); #endif /* !USE_WINDOWS_SSPI */ diff --git a/lib/curl_range.c b/lib/curl_range.c index e9620a29b535..c4118b07d9c8 100644 --- a/lib/curl_range.c +++ b/lib/curl_range.c @@ -23,18 +23,18 @@ ***************************************************************************/ #include "curl_setup.h" -#include + #include "curl_range.h" -#include "sendf.h" +#include "curl_trc.h" #include "curlx/strparse.h" /* Only include this function if one or more of FTP, FILE are enabled. */ #if !defined(CURL_DISABLE_FTP) || !defined(CURL_DISABLE_FILE) - /* - Check if this is a range download, and if so, set the internal variables - properly. - */ +/* + Check if this is a range download, and if so, set the internal variables + properly. +*/ CURLcode Curl_range(struct Curl_easy *data) { if(data->state.use_range && data->state.range) { diff --git a/lib/curl_range.h b/lib/curl_range.h index 77679e2b9448..842ada9ab106 100644 --- a/lib/curl_range.h +++ b/lib/curl_range.h @@ -25,6 +25,7 @@ ***************************************************************************/ #include "curl_setup.h" + #include "urldata.h" CURLcode Curl_range(struct Curl_easy *data); diff --git a/lib/curl_rtmp.c b/lib/curl_rtmp.c index 7006ca5eb94e..36f81464a4ea 100644 --- a/lib/curl_rtmp.c +++ b/lib/curl_rtmp.c @@ -30,27 +30,20 @@ #include "curl_rtmp.h" #include "urldata.h" #include "url.h" -#include "curlx/nonblock.h" /* for curlx_nonblock */ +#include "curlx/nonblock.h" #include "progress.h" /* for Curl_pgrsSetUploadSize */ #include "transfer.h" -#include "curlx/warnless.h" -#include -#include +#include "bufref.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" +#include -#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) -#define SET_RCVTIMEO(tv,s) int tv = s*1000 +#if defined(USE_WINSOCK) || defined(LWIP_SO_SNDRCVTIMEO_NONSTANDARD) +#define SET_RCVTIMEO(tv, s) int tv = s * 1000 #else -#define SET_RCVTIMEO(tv,s) struct timeval tv = {s,0} +#define SET_RCVTIMEO(tv, s) struct timeval tv = { s, 0 } #endif -#define DEF_BUFTIME (2*60*60*1000) /* 2 hours */ +#define DEF_BUFTIME (2 * 60 * 60 * 1000) /* 2 hours */ /* meta key for storing RTMP* at connection */ #define CURL_META_RTMP_CONN "meta:proto:rtmp:conn" @@ -68,7 +61,7 @@ static Curl_recv rtmp_recv; static Curl_send rtmp_send; /* - * RTMP protocol handler.h, based on https://rtmpdump.mplayerhq.hu + * RTMP protocol handler.h, based on https://rtmpdump.mplayerhq.hu/ */ const struct Curl_handler Curl_handler_rtmp = { @@ -240,10 +233,9 @@ static CURLcode rtmp_setup_connection(struct Curl_easy *data, RTMP_Init(r); RTMP_SetBufferMS(r, DEF_BUFTIME); - if(!RTMP_SetupURL(r, data->state.url)) { - RTMP_Free(r); + if(!RTMP_SetupURL(r, CURL_UNCONST(Curl_bufref_ptr(&data->state.url)))) + /* rtmp_conn_dtor() performs the cleanup */ return CURLE_URL_MALFORMAT; - } return CURLE_OK; } @@ -256,6 +248,11 @@ static CURLcode rtmp_connect(struct Curl_easy *data, bool *done) if(!r) return CURLE_FAILED_INIT; + if(conn->sock[FIRSTSOCKET] > INT_MAX) { + /* The socket value is invalid for rtmp. */ + return CURLE_FAILED_INIT; + } + r->m_sb.sb_socket = (int)conn->sock[FIRSTSOCKET]; /* We have to know if it is a write before we send the @@ -331,15 +328,15 @@ static CURLcode rtmp_recv(struct Curl_easy *data, int sockindex, char *buf, struct connectdata *conn = data->conn; RTMP *r = Curl_conn_meta_get(conn, CURL_META_RTMP_CONN); CURLcode result = CURLE_OK; - ssize_t nread; + ssize_t rv; (void)sockindex; *pnread = 0; if(!r) return CURLE_FAILED_INIT; - nread = RTMP_Read(r, buf, curlx_uztosi(len)); - if(nread < 0) { + rv = RTMP_Read(r, buf, curlx_uztosi(len)); + if(!curlx_sztouz(rv, pnread)) { if(r->m_read.status == RTMP_READ_COMPLETE || r->m_read.status == RTMP_READ_EOF) { data->req.size = data->req.bytecount; @@ -347,19 +344,17 @@ static CURLcode rtmp_recv(struct Curl_easy *data, int sockindex, char *buf, else result = CURLE_RECV_ERROR; } - else - *pnread = (size_t)nread; return result; } static CURLcode rtmp_send(struct Curl_easy *data, int sockindex, - const void *buf, size_t len, bool eos, + const uint8_t *buf, size_t len, bool eos, size_t *pnwritten) { struct connectdata *conn = data->conn; RTMP *r = Curl_conn_meta_get(conn, CURL_META_RTMP_CONN); - ssize_t nwritten; + ssize_t rv; (void)sockindex; (void)eos; @@ -367,11 +362,10 @@ static CURLcode rtmp_send(struct Curl_easy *data, int sockindex, if(!r) return CURLE_FAILED_INIT; - nwritten = RTMP_Write(r, (const char *)buf, curlx_uztosi(len)); - if(nwritten < 0) + rv = RTMP_Write(r, (const char *)buf, curlx_uztosi(len)); + if(!curlx_sztouz(rv, pnwritten)) return CURLE_SEND_ERROR; - *pnwritten = (size_t)nwritten; return CURLE_OK; } diff --git a/lib/curl_sasl.c b/lib/curl_sasl.c index c907c2c27bb2..f71c909a681b 100644 --- a/lib/curl_sasl.c +++ b/lib/curl_sasl.c @@ -39,22 +39,12 @@ !defined(CURL_DISABLE_POP3) || \ (!defined(CURL_DISABLE_LDAP) && defined(USE_OPENLDAP)) -#include #include "urldata.h" - #include "curlx/base64.h" -#include "curl_md5.h" #include "vauth/vauth.h" #include "cfilters.h" -#include "vtls/vtls.h" -#include "curl_hmac.h" #include "curl_sasl.h" -#include "curlx/warnless.h" -#include "sendf.h" - -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" +#include "curl_trc.h" /* Supported mechanisms */ static const struct { @@ -97,7 +87,7 @@ unsigned short Curl_sasl_decode_mech(const char *ptr, size_t maxlen, for(i = 0; mechtable[i].name; i++) { if(maxlen >= mechtable[i].len && - !memcmp(ptr, mechtable[i].name, mechtable[i].len)) { + curl_strnequal(ptr, mechtable[i].name, mechtable[i].len)) { if(len) *len = mechtable[i].len; @@ -240,7 +230,7 @@ static CURLcode get_server_message(struct SASL *sasl, struct Curl_easy *data, if(!result && (sasl->params->flags & SASL_FLAG_BASE64)) { unsigned char *msg; size_t msglen; - const char *serverdata = (const char *) Curl_bufref_ptr(out); + const char *serverdata = Curl_bufref_ptr(out); if(!*serverdata || *serverdata == '=') Curl_bufref_set(out, NULL, 0, NULL); @@ -268,7 +258,7 @@ static CURLcode build_message(struct SASL *sasl, struct bufref *msg) char *base64; size_t base64len; - result = curlx_base64_encode((const char *) Curl_bufref_ptr(msg), + result = curlx_base64_encode(Curl_bufref_uptr(msg), Curl_bufref_len(msg), &base64, &base64len); if(!result) Curl_bufref_set(msg, base64, base64len, curl_free); @@ -286,7 +276,7 @@ static CURLcode build_message(struct SASL *sasl, struct bufref *msg) bool Curl_sasl_can_authenticate(struct SASL *sasl, struct Curl_easy *data) { /* Have credentials been provided? */ - if(data->state.aptr.user) + if(data->conn->user[0]) return TRUE; /* EXTERNAL can authenticate without a username and/or password */ @@ -299,7 +289,6 @@ bool Curl_sasl_can_authenticate(struct SASL *sasl, struct Curl_easy *data) struct sasl_ctx { struct SASL *sasl; struct connectdata *conn; - const char *user; unsigned short enabledmechs; const char *mech; saslstate state1; @@ -325,8 +314,7 @@ static bool sasl_choose_external(struct Curl_easy *data, struct sasl_ctx *sctx) #ifdef USE_KERBEROS5 static bool sasl_choose_krb5(struct Curl_easy *data, struct sasl_ctx *sctx) { - if(sctx->user && - (sctx->enabledmechs & SASL_MECH_GSSAPI) && + if((sctx->enabledmechs & SASL_MECH_GSSAPI) && Curl_auth_is_gssapi_supported() && Curl_auth_user_contains_domain(sctx->conn->user)) { const char *service = data->set.str[STRING_SERVICE_NAME] ? @@ -360,8 +348,8 @@ static bool sasl_choose_gsasl(struct Curl_easy *data, struct sasl_ctx *sctx) struct gsasldata *gsasl; struct bufref nullmsg; - if(sctx->user && - (sctx->enabledmechs & (SASL_MECH_SCRAM_SHA_256|SASL_MECH_SCRAM_SHA_1))) { + if((sctx->enabledmechs & + (SASL_MECH_SCRAM_SHA_256 | SASL_MECH_SCRAM_SHA_1))) { gsasl = Curl_auth_gsasl_get(sctx->conn); if(!gsasl) { sctx->result = CURLE_OUT_OF_MEMORY; @@ -369,14 +357,14 @@ static bool sasl_choose_gsasl(struct Curl_easy *data, struct sasl_ctx *sctx) } if((sctx->enabledmechs & SASL_MECH_SCRAM_SHA_256) && - Curl_auth_gsasl_is_supported(data, SASL_MECH_STRING_SCRAM_SHA_256, - gsasl)) { + Curl_auth_gsasl_is_supported(data, SASL_MECH_STRING_SCRAM_SHA_256, + gsasl)) { sctx->mech = SASL_MECH_STRING_SCRAM_SHA_256; sctx->sasl->authused = SASL_MECH_SCRAM_SHA_256; } else if((sctx->enabledmechs & SASL_MECH_SCRAM_SHA_1) && - Curl_auth_gsasl_is_supported(data, SASL_MECH_STRING_SCRAM_SHA_1, - gsasl)) { + Curl_auth_gsasl_is_supported(data, SASL_MECH_STRING_SCRAM_SHA_1, + gsasl)) { sctx->mech = SASL_MECH_STRING_SCRAM_SHA_1; sctx->sasl->authused = SASL_MECH_SCRAM_SHA_1; } @@ -401,9 +389,7 @@ static bool sasl_choose_gsasl(struct Curl_easy *data, struct sasl_ctx *sctx) static bool sasl_choose_digest(struct Curl_easy *data, struct sasl_ctx *sctx) { (void)data; - if(!sctx->user) - return FALSE; - else if((sctx->enabledmechs & SASL_MECH_DIGEST_MD5) && + if((sctx->enabledmechs & SASL_MECH_DIGEST_MD5) && Curl_auth_is_digest_supported()) { sctx->mech = SASL_MECH_STRING_DIGEST_MD5; sctx->state1 = SASL_DIGESTMD5; @@ -423,10 +409,8 @@ static bool sasl_choose_digest(struct Curl_easy *data, struct sasl_ctx *sctx) #ifdef USE_NTLM static bool sasl_choose_ntlm(struct Curl_easy *data, struct sasl_ctx *sctx) { - if(!sctx->user) - return FALSE; - else if((sctx->enabledmechs & SASL_MECH_NTLM) && - Curl_auth_is_ntlm_supported()) { + if((sctx->enabledmechs & SASL_MECH_NTLM) && + Curl_auth_is_ntlm_supported()) { const char *service = data->set.str[STRING_SERVICE_NAME] ? data->set.str[STRING_SERVICE_NAME] : sctx->sasl->params->service; @@ -457,10 +441,11 @@ static bool sasl_choose_ntlm(struct Curl_easy *data, struct sasl_ctx *sctx) static bool sasl_choose_oauth(struct Curl_easy *data, struct sasl_ctx *sctx) { - const char *oauth_bearer = data->set.str[STRING_BEARER]; + const char *oauth_bearer = + (!data->state.this_is_a_follow || data->set.allow_auth_to_other_hosts) ? + data->set.str[STRING_BEARER] : NULL; - if(sctx->user && oauth_bearer && - (sctx->enabledmechs & SASL_MECH_OAUTHBEARER)) { + if(oauth_bearer && (sctx->enabledmechs & SASL_MECH_OAUTHBEARER)) { const char *hostname; int port; Curl_conn_get_current_host(data, FIRSTSOCKET, &hostname, &port); @@ -482,10 +467,11 @@ static bool sasl_choose_oauth(struct Curl_easy *data, struct sasl_ctx *sctx) static bool sasl_choose_oauth2(struct Curl_easy *data, struct sasl_ctx *sctx) { - const char *oauth_bearer = data->set.str[STRING_BEARER]; + const char *oauth_bearer = + (!data->state.this_is_a_follow || data->set.allow_auth_to_other_hosts) ? + data->set.str[STRING_BEARER] : NULL; - if(sctx->user && oauth_bearer && - (sctx->enabledmechs & SASL_MECH_XOAUTH2)) { + if(oauth_bearer && (sctx->enabledmechs & SASL_MECH_XOAUTH2)) { sctx->mech = SASL_MECH_STRING_XOAUTH2; sctx->state1 = SASL_OAUTH2; sctx->sasl->authused = SASL_MECH_XOAUTH2; @@ -501,7 +487,7 @@ static bool sasl_choose_oauth2(struct Curl_easy *data, struct sasl_ctx *sctx) static bool sasl_choose_plain(struct Curl_easy *data, struct sasl_ctx *sctx) { - if(sctx->user && (sctx->enabledmechs & SASL_MECH_PLAIN)) { + if(sctx->enabledmechs & SASL_MECH_PLAIN) { sctx->mech = SASL_MECH_STRING_PLAIN; sctx->state1 = SASL_PLAIN; sctx->sasl->authused = SASL_MECH_PLAIN; @@ -518,7 +504,7 @@ static bool sasl_choose_plain(struct Curl_easy *data, struct sasl_ctx *sctx) static bool sasl_choose_login(struct Curl_easy *data, struct sasl_ctx *sctx) { - if(sctx->user && (sctx->enabledmechs & SASL_MECH_LOGIN)) { + if(sctx->enabledmechs & SASL_MECH_LOGIN) { sctx->mech = SASL_MECH_STRING_LOGIN; sctx->state1 = SASL_LOGIN; sctx->state2 = SASL_LOGIN_PASSWD; @@ -548,7 +534,6 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct Curl_easy *data, memset(&sctx, 0, sizeof(sctx)); sctx.sasl = sasl; sctx.conn = data->conn; - sctx.user = data->state.aptr.user; Curl_bufref_init(&sctx.resp); sctx.enabledmechs = sasl->authmechs & sasl->prefmech; sctx.state1 = SASL_STOP; @@ -710,7 +695,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct Curl_easy *data, case SASL_NTLM_TYPE2MSG: { /* Decode the type-2 message */ struct ntlmdata *ntlm = Curl_auth_ntlm_get(conn, FALSE); - result = !ntlm ? CURLE_FAILED_INIT : + result = !ntlm ? CURLE_OUT_OF_MEMORY : get_server_message(sasl, data, &serverdata); if(!result) result = Curl_auth_decode_ntlm_type2_message(data, &serverdata, ntlm); @@ -877,7 +862,7 @@ static void sasl_unchosen(struct Curl_easy *data, unsigned short mech, else { if(param_missing) infof(data, "SASL: %s is missing %s", mname, param_missing); - if(!data->state.aptr.user) + if(!data->conn->user[0]) infof(data, "SASL: %s is missing username", mname); } } @@ -933,10 +918,10 @@ CURLcode Curl_sasl_is_blocked(struct SASL *sasl, struct Curl_easy *data) CURL_SASL_DIGEST, TRUE, NULL); sasl_unchosen(data, SASL_MECH_NTLM, enabledmechs, CURL_SASL_NTLM, Curl_auth_is_ntlm_supported(), NULL); - sasl_unchosen(data, SASL_MECH_OAUTHBEARER, enabledmechs, TRUE, TRUE, + sasl_unchosen(data, SASL_MECH_OAUTHBEARER, enabledmechs, TRUE, TRUE, data->set.str[STRING_BEARER] ? NULL : "CURLOPT_XOAUTH2_BEARER"); - sasl_unchosen(data, SASL_MECH_XOAUTH2, enabledmechs, TRUE, TRUE, + sasl_unchosen(data, SASL_MECH_XOAUTH2, enabledmechs, TRUE, TRUE, data->set.str[STRING_BEARER] ? NULL : "CURLOPT_XOAUTH2_BEARER"); } diff --git a/lib/curl_sasl.h b/lib/curl_sasl.h index 0674d56f8650..0632e09ebdd3 100644 --- a/lib/curl_sasl.h +++ b/lib/curl_sasl.h @@ -24,8 +24,6 @@ * ***************************************************************************/ -#include - #include "bufref.h" struct Curl_easy; diff --git a/lib/curl_setup.h b/lib/curl_setup.h index 694d14df4f09..e3903f475acf 100644 --- a/lib/curl_setup.h +++ b/lib/curl_setup.h @@ -75,14 +75,14 @@ #endif #endif -#if defined(__MINGW32__) && !defined(__MINGW32CE__) && \ +#if defined(__MINGW32__) && \ (!defined(__MINGW64_VERSION_MAJOR) || (__MINGW64_VERSION_MAJOR < 3)) #error "Building curl requires mingw-w64 3.0 or later" #endif -/* Visual Studio 2008 is the minimum Visual Studio version we support. +/* Visual Studio 2010 is the minimum Visual Studio version we support. Workarounds for older versions of Visual Studio have been removed. */ -#if defined(_MSC_VER) && (_MSC_VER < 1500) +#if defined(_MSC_VER) && (_MSC_VER < 1600) #error "Ancient versions of Visual Studio are no longer supported due to bugs." #endif @@ -90,11 +90,11 @@ /* Disable Visual Studio warnings: 4127 "conditional expression is constant" */ #pragma warning(disable:4127) /* Avoid VS2005 and upper complaining about portable C functions. */ -#ifndef _CRT_NONSTDC_NO_DEPRECATE -#define _CRT_NONSTDC_NO_DEPRECATE /* for strdup(), write(), etc. */ +#ifndef _CRT_NONSTDC_NO_DEPRECATE /* mingw-w64 v2+. MS SDK ~10+/~VS2017+. */ +#define _CRT_NONSTDC_NO_DEPRECATE /* for close(), fileno(), unlink(), etc. */ #endif -#ifndef _CRT_SECURE_NO_DEPRECATE -#define _CRT_SECURE_NO_DEPRECATE /* for fopen(), getenv(), etc. */ +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS /* for getenv(), strcpy(), tests: sscanf() */ #endif #endif /* _MSC_VER */ @@ -122,14 +122,6 @@ # endif #endif -/* Avoid bogus format check warnings with mingw32ce gcc 4.4.0 in - C99 (-std=gnu99) mode */ -#if defined(__MINGW32CE__) && !defined(CURL_NO_FMT_CHECKS) && \ - (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) && \ - (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 4)) -#define CURL_NO_FMT_CHECKS -#endif - /* Compatibility */ #ifdef ENABLE_IPV6 #define USE_IPV6 1 @@ -170,7 +162,7 @@ /* ================================================================ */ /* Definition of preprocessor macros/symbols which modify compiler */ -/* behavior or generated code characteristics must be done here, */ +/* behavior or generated code characteristics must be done here, */ /* as appropriate, before any system header file is included. It is */ /* also possible to have them defined in the config file included */ /* before this point. As a result of all this we frown inclusion of */ @@ -187,7 +179,6 @@ * AIX 4.3 and newer needs _THREAD_SAFE defined to build * proper reentrant code. Others may also need it. */ - #ifdef NEED_THREAD_SAFE # ifndef _THREAD_SAFE # define _THREAD_SAFE @@ -199,7 +190,6 @@ * things to appear in the system header files. Unixware needs it * to build proper reentrant code. Others may also need it. */ - #ifdef NEED_REENTRANT # ifndef _REENTRANT # define _REENTRANT @@ -226,7 +216,6 @@ /* * Disable other protocols when http is the only one desired. */ - #ifdef HTTP_ONLY # ifndef CURL_DISABLE_DICT # define CURL_DISABLE_DICT @@ -275,7 +264,6 @@ /* * When http is disabled rtsp is not supported. */ - #if defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_RTSP) # define CURL_DISABLE_RTSP #endif @@ -283,7 +271,6 @@ /* * When HTTP is disabled, disable HTTP-only features */ - #ifdef CURL_DISABLE_HTTP # define CURL_DISABLE_ALTSVC 1 # define CURL_DISABLE_COOKIES 1 @@ -305,7 +292,6 @@ /* * OS/400 setup file includes some system headers. */ - #ifdef __OS400__ # include "setup-os400.h" #endif @@ -313,7 +299,6 @@ /* * VMS setup file includes some system headers. */ - #ifdef __VMS # include "setup-vms.h" #endif @@ -321,7 +306,6 @@ /* * Windows setup file includes some system headers. */ - #ifdef _WIN32 # include "setup-win32.h" #endif @@ -332,8 +316,8 @@ * Direct macros concatenation does not work because macros * are not expanded before direct concatenation. */ -#define CURL_CONC_MACROS_(A,B) A ## B -#define CURL_CONC_MACROS(A,B) CURL_CONC_MACROS_(A,B) +#define CURL_CONC_MACROS_(A, B) A ## B +#define CURL_CONC_MACROS(A, B) CURL_CONC_MACROS_(A, B) /* curl uses its own printf() function internally. It understands the GNU * format. Use this format, so that it matches the GNU format attribute we @@ -347,7 +331,6 @@ #endif /* based on logic in "curl/mprintf.h" */ - #if (defined(__GNUC__) || defined(__clang__) || \ defined(__IAR_SYSTEMS_ICC__)) && \ defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ @@ -438,9 +421,9 @@ # ifdef __amigaos4__ int Curl_amiga_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout); -# define select(a,b,c,d,e) Curl_amiga_select(a,b,c,d,e) +# define select(a, b, c, d, e) Curl_amiga_select(a, b, c, d, e) # else -# define select(a,b,c,d,e) WaitSelect(a,b,c,d,e,0) +# define select(a, b, c, d, e) WaitSelect(a, b, c, d, e, 0) # endif /* must not use libc's fcntl() on bsdsocket.library sockfds! */ # undef HAVE_FCNTL @@ -466,7 +449,7 @@ #include #ifdef __TANDEM /* for ns*-tandem-nsk systems */ -# if ! defined __LP64 +# ifndef __LP64 # include /* FLOSS is only used for 32-bit builds. */ # endif #endif @@ -487,31 +470,19 @@ # endif # include # include -# ifdef USE_WIN32_LARGE_FILES - /* Large file (>2Gb) support using Win32 functions. */ -# undef lseek -# define lseek(fdes, offset, whence) _lseeki64(fdes, offset, whence) -# undef fstat -# define fstat(fdes,stp) _fstati64(fdes, stp) -# undef stat -# define struct_stat struct _stati64 -# define LSEEK_ERROR (__int64)-1 -# else - /* Small file (<2Gb) support using Win32 functions. */ -# ifndef UNDER_CE -# undef lseek -# define lseek(fdes, offset, whence) _lseek(fdes, (long)offset, whence) -# define fstat(fdes, stp) _fstat(fdes, stp) -# define struct_stat struct _stat -# endif -# define LSEEK_ERROR (long)-1 -# endif + /* Large file (>2Gb) support using Win32 functions. */ +# undef lseek +# define lseek(fdes, offset, whence) _lseeki64(fdes, offset, whence) +# undef fstat +# define fstat(fdes, stp) _fstati64(fdes, stp) +# define struct_stat struct _stati64 +# define LSEEK_ERROR (__int64)-1 #elif defined(__DJGPP__) /* Requires DJGPP 2.04 */ # include # undef lseek -# define lseek(fdes,offset,whence) llseek(fdes, offset, whence) -# define LSEEK_ERROR (offset_t)-1 +# define lseek(fdes, offset, whence) llseek(fdes, offset, whence) +# define LSEEK_ERROR (offset_t)-1 #endif #ifndef struct_stat @@ -538,9 +509,13 @@ #endif #if SIZEOF_CURL_SOCKET_T < 8 +#ifdef _WIN32 +# define FMT_SOCKET_T "u" +#else # define FMT_SOCKET_T "d" -#elif defined(__MINGW32__) -# define FMT_SOCKET_T "zd" +#endif +#elif defined(_WIN32) +# define FMT_SOCKET_T "zu" #else # define FMT_SOCKET_T "qd" #endif @@ -580,21 +555,7 @@ #endif #define CURL_OFF_T_MIN (-CURL_OFF_T_MAX - 1) -#if (SIZEOF_CURL_OFF_T != 8) -# error "curl_off_t must be exactly 64 bits" -#else - typedef unsigned CURL_TYPEOF_CURL_OFF_T curl_uint64_t; - typedef CURL_TYPEOF_CURL_OFF_T curl_int64_t; -# ifndef CURL_SUFFIX_CURL_OFF_TU -# error "CURL_SUFFIX_CURL_OFF_TU must be defined" -# endif -# define CURL_UINT64_SUFFIX CURL_SUFFIX_CURL_OFF_TU -# define CURL_UINT64_C(val) CURL_CONC_MACROS(val,CURL_UINT64_SUFFIX) -# define FMT_PRId64 CURL_FORMAT_CURL_OFF_T -# define FMT_PRIu64 CURL_FORMAT_CURL_OFF_TU -#endif - -#define FMT_OFF_T CURL_FORMAT_CURL_OFF_T +#define FMT_OFF_T CURL_FORMAT_CURL_OFF_T #define FMT_OFF_TU CURL_FORMAT_CURL_OFF_TU #if (SIZEOF_TIME_T == 4) @@ -633,10 +594,13 @@ #endif #endif +#if SIZEOF_LONG > SIZEOF_SIZE_T +#error "unexpected: 'long' is larger than 'size_t'" +#endif + /* * Arg 2 type for gethostname in case it has not been defined in config file. */ - #ifndef GETHOSTNAME_TYPE_ARG2 # ifdef USE_WINSOCK # define GETHOSTNAME_TYPE_ARG2 int @@ -646,10 +610,9 @@ #endif /* Below we define some functions. They should - 4. set the SIGALRM signal timeout 5. set dir/file naming defines - */ + */ #ifdef _WIN32 @@ -660,8 +623,8 @@ # ifdef MSDOS /* Watt-32 */ # include -# define select(n,r,w,x,t) select_s(n,r,w,x,t) -# define ioctl(x,y,z) ioctlsocket(x,y,(char *)(z)) +# define select(n, r, w, x, t) select_s(n, r, w, x, t) +# define ioctl(x, y, z) ioctlsocket(x, y, (char *)(z)) # include # undef word # undef byte @@ -685,7 +648,6 @@ /* * Mutually exclusive CURLRES_* definitions. */ - #if defined(USE_IPV6) && defined(HAVE_GETADDRINFO) # define CURLRES_IPV6 #elif defined(USE_IPV6) && (defined(_WIN32) || defined(__CYGWIN__)) @@ -756,8 +718,9 @@ /* Single point where USE_NTLM definition might be defined */ #ifndef CURL_DISABLE_NTLM -# if defined(USE_OPENSSL) || defined(USE_MBEDTLS) || \ +# if (defined(USE_OPENSSL) && defined(HAVE_DES_ECB_ENCRYPT)) || \ defined(USE_GNUTLS) || \ + (defined(USE_MBEDTLS) && defined(HAVE_MBEDTLS_DES_CRYPT_ECB)) || \ defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \ (defined(USE_WOLFSSL) && defined(HAVE_WOLFSSL_DES_ECB_ENCRYPT)) # define USE_CURL_NTLM_CORE @@ -812,44 +775,32 @@ /* * Include macros and defines that should only be processed once. */ - #ifndef HEADER_CURL_SETUP_ONCE_H #include "curl_setup_once.h" #endif -#ifdef UNDER_CE -#define getenv curl_getenv /* Windows CE does not support getenv() */ -#define raise(s) ((void)(s)) -/* Terrible workarounds to make Windows CE compile */ -#define errno 0 -#define CURL_SETERRNO(x) ((void)(x)) -#define EINTR 4 -#define EAGAIN 11 -#define ENOMEM 12 -#define EACCES 13 -#define EEXIST 17 -#define EISDIR 21 -#define EINVAL 22 -#define ENOSPC 28 -#define strerror(x) "?" -#undef STDIN_FILENO -#define STDIN_FILENO 0 -#else -#define CURL_SETERRNO(x) (errno = (x)) +/* + * Macros and functions to safely suppress warnings + */ +#include "curlx/warnless.h" + +#ifdef _WIN32 +# undef read +# define read(fd, buf, count) (ssize_t)_read(fd, buf, curlx_uztoui(count)) +# undef write +# define write(fd, buf, count) (ssize_t)_write(fd, buf, curlx_uztoui(count)) #endif /* * Definition of our NOP statement Object-like macro */ - #ifndef Curl_nop_stmt -#define Curl_nop_stmt do { } while(0) +#define Curl_nop_stmt do {} while(0) #endif /* * Ensure that Winsock and lwIP TCP/IP stacks are not mixed. */ - #if defined(__LWIP_OPT_H__) || defined(LWIP_HDR_OPT_H) # if defined(SOCKET) || defined(USE_WINSOCK) # error "Winsock and lwIP TCP/IP stack definitions shall not coexist!" @@ -859,7 +810,6 @@ /* * shutdown() flags for systems that do not define them */ - #ifndef SHUT_RD #define SHUT_RD 0x00 #endif @@ -905,8 +855,8 @@ Therefore we specify it explicitly. https://github.com/curl/curl/pull/258 */ #if defined(_WIN32) || defined(MSDOS) -#define FOPEN_READTEXT "rt" -#define FOPEN_WRITETEXT "wt" +#define FOPEN_READTEXT "rt" +#define FOPEN_WRITETEXT "wt" #define FOPEN_APPENDTEXT "at" #elif defined(__CYGWIN__) /* Cygwin has specific behavior we need to address when _WIN32 is not defined. @@ -915,18 +865,18 @@ For write we want our output to have line endings of LF and be compatible with other Cygwin utilities. For read we want to handle input that may have line endings either CRLF or LF so 't' is appropriate. */ -#define FOPEN_READTEXT "rt" -#define FOPEN_WRITETEXT "w" +#define FOPEN_READTEXT "rt" +#define FOPEN_WRITETEXT "w" #define FOPEN_APPENDTEXT "a" #else -#define FOPEN_READTEXT "r" -#define FOPEN_WRITETEXT "w" +#define FOPEN_READTEXT "r" +#define FOPEN_WRITETEXT "w" #define FOPEN_APPENDTEXT "a" #endif /* for systems that do not detect this in configure */ #ifndef CURL_SA_FAMILY_T -# if defined(_WIN32) && !defined(UNDER_CE) +# ifdef _WIN32 # define CURL_SA_FAMILY_T ADDRESS_FAMILY # elif defined(HAVE_SA_FAMILY_T) # define CURL_SA_FAMILY_T sa_family_t @@ -940,15 +890,15 @@ endings either CRLF or LF so 't' is appropriate. /* Some convenience macros to get the larger/smaller value out of two given. We prefix with CURL to prevent name collisions. */ -#define CURLMAX(x,y) ((x)>(y)?(x):(y)) -#define CURLMIN(x,y) ((x)<(y)?(x):(y)) +#define CURLMAX(x, y) ((x) > (y) ? (x) : (y)) +#define CURLMIN(x, y) ((x) < (y) ? (x) : (y)) /* A convenience macro to provide both the string literal and the length of the string literal in one go, useful for functions that take "string,len" as their argument */ -#define STRCONST(x) x,sizeof(x)-1 +#define STRCONST(x) x, sizeof(x) - 1 -#define CURL_ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) +#define CURL_ARRAYSIZE(A) (sizeof(A) / sizeof((A)[0])) /* Buffer size for error messages retrieved via curlx_strerror() and Curl_sspi_strerror() */ @@ -981,9 +931,12 @@ extern curl_calloc_callback Curl_ccalloc; * This macro also assigns NULL to given pointer when free'd. */ #define Curl_safefree(ptr) \ - do { free((ptr)); (ptr) = NULL;} while(0) + do { \ + curlx_free(ptr); \ + (ptr) = NULL; \ + } while(0) -#include /* for CURL_EXTERN, mprintf.h */ +#include /* for CURL_EXTERN, curl_socket_t, mprintf.h */ #ifdef CURLDEBUG #ifdef __clang__ @@ -1064,35 +1017,36 @@ CURL_EXTERN RECV_TYPE_RETV curl_dbg_recv(RECV_TYPE_ARG1 sockfd, /* FILE functions */ CURL_EXTERN int curl_dbg_fclose(FILE *file, int line, const char *source); -CURL_EXTERN ALLOC_FUNC - FILE *curl_dbg_fopen(const char *file, const char *mode, - int line, const char *source); -CURL_EXTERN ALLOC_FUNC - FILE *curl_dbg_fdopen(int filedes, const char *mode, - int line, const char *source); - -#define sclose(sockfd) curl_dbg_sclose(sockfd,__LINE__,__FILE__) -#define fake_sclose(sockfd) curl_dbg_mark_sclose(sockfd,__LINE__,__FILE__) - -#define CURL_GETADDRINFO(host,serv,hint,res) \ +CURL_EXTERN ALLOC_FUNC FILE *curl_dbg_fopen(const char *file, const char *mode, + int line, const char *source); +CURL_EXTERN ALLOC_FUNC FILE *curl_dbg_freopen(const char *file, + const char *mode, FILE *fh, + int line, const char *source); +CURL_EXTERN ALLOC_FUNC FILE *curl_dbg_fdopen(int filedes, const char *mode, + int line, const char *source); + +#define sclose(sockfd) curl_dbg_sclose(sockfd, __LINE__, __FILE__) +#define fake_sclose(sockfd) curl_dbg_mark_sclose(sockfd, __LINE__, __FILE__) + +#define CURL_GETADDRINFO(host, serv, hint, res) \ curl_dbg_getaddrinfo(host, serv, hint, res, __LINE__, __FILE__) #define CURL_FREEADDRINFO(data) \ curl_dbg_freeaddrinfo(data, __LINE__, __FILE__) -#define CURL_SOCKET(domain,type,protocol) \ +#define CURL_SOCKET(domain, type, protocol) \ curl_dbg_socket((int)domain, type, protocol, __LINE__, __FILE__) #ifdef HAVE_SOCKETPAIR -#define CURL_SOCKETPAIR(domain,type,protocol,socket_vector) \ +#define CURL_SOCKETPAIR(domain, type, protocol, socket_vector) \ curl_dbg_socketpair((int)domain, type, protocol, socket_vector, \ __LINE__, __FILE__) #endif -#define CURL_ACCEPT(sock,addr,len) \ +#define CURL_ACCEPT(sock, addr, len) \ curl_dbg_accept(sock, addr, len, __LINE__, __FILE__) #ifdef HAVE_ACCEPT4 -#define CURL_ACCEPT4(sock,addr,len,flags) \ +#define CURL_ACCEPT4(sock, addr, len, flags) \ curl_dbg_accept4(sock, addr, len, flags, __LINE__, __FILE__) #endif -#define CURL_SEND(a,b,c,d) curl_dbg_send(a,b,c,d, __LINE__, __FILE__) -#define CURL_RECV(a,b,c,d) curl_dbg_recv(a,b,c,d, __LINE__, __FILE__) +#define CURL_SEND(a, b, c, d) curl_dbg_send(a, b, c, d, __LINE__, __FILE__) +#define CURL_RECV(a, b, c, d) curl_dbg_recv(a, b, c, d, __LINE__, __FILE__) #else /* !CURLDEBUG */ @@ -1114,6 +1068,56 @@ CURL_EXTERN ALLOC_FUNC #endif /* CURLDEBUG */ +/* Allocator macros */ + +#ifdef CURLDEBUG + +#define curlx_strdup(ptr) curl_dbg_strdup(ptr, __LINE__, __FILE__) +#define curlx_malloc(size) curl_dbg_malloc(size, __LINE__, __FILE__) +#define curlx_calloc(nbelem, size) \ + curl_dbg_calloc(nbelem, size, __LINE__, __FILE__) +#define curlx_realloc(ptr, size) \ + curl_dbg_realloc(ptr, size, __LINE__, __FILE__) +#define curlx_free(ptr) curl_dbg_free(ptr, __LINE__, __FILE__) + +#ifdef _WIN32 +#ifdef UNICODE +#define curlx_tcsdup(ptr) curl_dbg_wcsdup(ptr, __LINE__, __FILE__) +#else +#define curlx_tcsdup(ptr) curlx_strdup(ptr) +#endif +#endif /* _WIN32 */ + +#else /* !CURLDEBUG */ + +#ifdef BUILDING_LIBCURL +#define curlx_strdup(ptr) Curl_cstrdup(ptr) +#define curlx_malloc(size) Curl_cmalloc(size) +#define curlx_calloc(nbelem, size) Curl_ccalloc(nbelem, size) +#define curlx_realloc(ptr, size) Curl_crealloc(ptr, size) +#define curlx_free(ptr) Curl_cfree(ptr) +#else /* !BUILDING_LIBCURL */ +#ifdef _WIN32 +#define curlx_strdup(ptr) _strdup(ptr) +#else +#define curlx_strdup(ptr) strdup(ptr) +#endif +#define curlx_malloc(size) malloc(size) +#define curlx_calloc(nbelem, size) calloc(nbelem, size) +#define curlx_realloc(ptr, size) realloc(ptr, size) +#define curlx_free(ptr) free(ptr) +#endif /* BUILDING_LIBCURL */ + +#ifdef _WIN32 +#ifdef UNICODE +#define curlx_tcsdup(ptr) Curl_wcsdup(ptr) +#else +#define curlx_tcsdup(ptr) curlx_strdup(ptr) +#endif +#endif /* _WIN32 */ + +#endif /* CURLDEBUG */ + /* Some versions of the Android NDK is missing the declaration */ #if defined(HAVE_GETPWUID_R) && \ defined(__ANDROID_API__) && (__ANDROID_API__ < 21) @@ -1133,8 +1137,8 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, #endif #if (defined(USE_NGTCP2) && defined(USE_NGHTTP3)) || \ - (defined(USE_OPENSSL_QUIC) && defined(USE_NGHTTP3)) || \ - defined(USE_QUICHE) + (defined(USE_OPENSSL_QUIC) && defined(USE_NGHTTP3)) || \ + defined(USE_QUICHE) #ifdef CURL_WITH_MULTI_SSL #error "MultiSSL combined with QUIC is not supported" @@ -1156,17 +1160,17 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, #endif #if defined(USE_UNIX_SOCKETS) && defined(_WIN32) -# ifndef UNIX_PATH_MAX - /* Replicating logic present in afunix.h - (distributed with newer Windows 10 SDK versions only) */ -# define UNIX_PATH_MAX 108 - /* !checksrc! disable TYPEDEFSTRUCT 1 */ - typedef struct sockaddr_un { - CURL_SA_FAMILY_T sun_family; - char sun_path[UNIX_PATH_MAX]; - } SOCKADDR_UN, *PSOCKADDR_UN; -# define WIN32_SOCKADDR_UN -# endif +/* Offered by mingw-w64 v10+. MS SDK 10.17763/~VS2017+. */ +#if defined(__MINGW32__) && (__MINGW64_VERSION_MAJOR >= 10) +# include +#elif !defined(UNIX_PATH_MAX) /* Replicate logic present in afunix.h */ +# define UNIX_PATH_MAX 108 +/* !checksrc! disable TYPEDEFSTRUCT 1 */ +typedef struct sockaddr_un { + CURL_SA_FAMILY_T sun_family; + char sun_path[UNIX_PATH_MAX]; +} SOCKADDR_UN, *PSOCKADDR_UN; +#endif #endif #ifdef USE_OPENSSL @@ -1204,5 +1208,3 @@ int getpwuid_r(uid_t uid, struct passwd *pwd, char *buf, #endif #endif /* HEADER_CURL_SETUP_H */ - -#include "curl_mem_undef.h" diff --git a/lib/curl_setup_once.h b/lib/curl_setup_once.h index 7a54760e161e..06ccc98639fd 100644 --- a/lib/curl_setup_once.h +++ b/lib/curl_setup_once.h @@ -28,14 +28,11 @@ * Inclusion of common header files. */ -#include #include #include #include #include -#ifndef UNDER_CE #include -#endif #ifdef HAVE_SYS_TYPES_H #include @@ -67,8 +64,6 @@ Use it for APIs that do not or cannot support the const qualifier. */ #ifdef HAVE_STDINT_H # define CURL_UNCONST(p) ((void *)(uintptr_t)(const void *)(p)) -#elif defined(_WIN32) /* for VS2008 */ -# define CURL_UNCONST(p) ((void *)(ULONG_PTR)(const void *)(p)) #else # define CURL_UNCONST(p) ((void *)(p)) /* Fall back to simple cast */ #endif @@ -108,7 +103,6 @@ /* * Definition of timeval struct for platforms that do not have it. */ - #ifndef HAVE_STRUCT_TIMEVAL struct timeval { long tv_sec; @@ -116,24 +110,21 @@ struct timeval { }; #endif - /* * If we have the MSG_NOSIGNAL define, make sure we use * it as the fourth argument of function send() */ - #ifdef HAVE_MSG_NOSIGNAL #define SEND_4TH_ARG MSG_NOSIGNAL #else #define SEND_4TH_ARG 0 #endif - #ifdef __minix /* Minix does not support recv on TCP sockets */ -#define sread(x,y,z) (ssize_t)read((RECV_TYPE_ARG1)(x), \ - (RECV_TYPE_ARG2)(y), \ - (RECV_TYPE_ARG3)(z)) +#define sread(x, y, z) (ssize_t)read((RECV_TYPE_ARG1)(x), \ + (RECV_TYPE_ARG2)(y), \ + (RECV_TYPE_ARG3)(z)) #elif defined(HAVE_RECV) /* @@ -158,48 +149,45 @@ struct timeval { * SEND_TYPE_RETV must also be defined. */ -#define sread(x,y,z) (ssize_t)recv((RECV_TYPE_ARG1)(x), \ - (RECV_TYPE_ARG2)(y), \ - (RECV_TYPE_ARG3)(z), \ - (RECV_TYPE_ARG4)(0)) +#define sread(x, y, z) (ssize_t)recv((RECV_TYPE_ARG1)(x), \ + (RECV_TYPE_ARG2)(y), \ + (RECV_TYPE_ARG3)(z), \ + (RECV_TYPE_ARG4)(0)) #else /* HAVE_RECV */ #ifndef sread #error "Missing definition of macro sread!" #endif #endif /* HAVE_RECV */ - #ifdef __minix /* Minix does not support send on TCP sockets */ -#define swrite(x,y,z) (ssize_t)write((SEND_TYPE_ARG1)(x), \ - (SEND_TYPE_ARG2)CURL_UNCONST(y), \ - (SEND_TYPE_ARG3)(z)) +#define swrite(x, y, z) (ssize_t)write((SEND_TYPE_ARG1)(x), \ + (SEND_TYPE_ARG2)CURL_UNCONST(y), \ + (SEND_TYPE_ARG3)(z)) #elif defined(HAVE_SEND) -#define swrite(x,y,z) (ssize_t)send((SEND_TYPE_ARG1)(x), \ +#define swrite(x, y, z) (ssize_t)send((SEND_TYPE_ARG1)(x), \ (SEND_QUAL_ARG2 SEND_TYPE_ARG2)CURL_UNCONST(y), \ - (SEND_TYPE_ARG3)(z), \ - (SEND_TYPE_ARG4)(SEND_4TH_ARG)) + (SEND_TYPE_ARG3)(z), \ + (SEND_TYPE_ARG4)(SEND_4TH_ARG)) #else /* HAVE_SEND */ #ifndef swrite #error "Missing definition of macro swrite!" #endif #endif /* HAVE_SEND */ - /* * Function-like macro definition used to close a socket. */ - #ifdef HAVE_CLOSESOCKET -# define CURL_SCLOSE(x) closesocket((x)) +# define CURL_SCLOSE(x) closesocket(x) #elif defined(HAVE_CLOSESOCKET_CAMEL) -# define CURL_SCLOSE(x) CloseSocket((x)) +# define CURL_SCLOSE(x) CloseSocket(x) #elif defined(MSDOS) /* Watt-32 */ -# define CURL_SCLOSE(x) close_s((x)) +# define CURL_SCLOSE(x) close_s(x) #elif defined(USE_LWIPSOCK) -# define CURL_SCLOSE(x) lwip_close((x)) +# define CURL_SCLOSE(x) lwip_close(x) #else -# define CURL_SCLOSE(x) close((x)) +# define CURL_SCLOSE(x) close(x) #endif /* @@ -214,7 +202,6 @@ struct timeval { /* * 'bool' stuff compatible with HP-UX headers. */ - #if defined(__hpux) && !defined(HAVE_BOOL_T) typedef int bool; # define false 0 @@ -222,14 +209,12 @@ struct timeval { # define HAVE_BOOL_T #endif - /* * 'bool' exists on platforms with , i.e. C99 platforms. * On non-C99 platforms there is no bool, so define an enum for that. * On C99 platforms 'false' and 'true' also exist. Enum uses a * global namespace though, so use bool_false and bool_true. */ - #ifndef HAVE_BOOL_T typedef enum { bool_false = 0, @@ -262,7 +247,6 @@ typedef unsigned int bit; * 'bool found = TRUE' will not. Change tested on IRIX/MIPSPro, * AIX 5.1/Xlc, Tru64 5.1/cc, w/make test too. */ - #ifndef TRUE #define TRUE true #endif @@ -272,35 +256,29 @@ typedef unsigned int bit; #include "curl_ctype.h" - /* * Macro used to include code only in debug builds. */ - #ifdef DEBUGBUILD #define DEBUGF(x) x #else -#define DEBUGF(x) do { } while(0) +#define DEBUGF(x) do {} while(0) #endif - /* * Macro used to include assertion code only in debug builds. */ - #undef DEBUGASSERT #ifdef DEBUGBUILD #define DEBUGASSERT(x) assert(x) #else -#define DEBUGASSERT(x) do { } while(0) +#define DEBUGASSERT(x) do {} while(0) #endif - /* * Macro SOCKERRNO / SET_SOCKERRNO() returns / sets the *socket-related* errno * (or equivalent) on this platform to hide platform details to code using it. */ - #ifdef USE_WINSOCK #define SOCKERRNO ((int)WSAGetLastError()) #define SET_SOCKERRNO(x) (WSASetLastError((int)(x))) @@ -309,11 +287,9 @@ typedef unsigned int bit; #define SET_SOCKERRNO(x) (errno = (x)) #endif - /* * Portable error number symbolic names defined to Winsock error codes. */ - #ifdef USE_WINSOCK #define SOCKEACCES WSAEACCES #define SOCKEADDRINUSE WSAEADDRINUSE @@ -353,22 +329,18 @@ typedef unsigned int bit; /* * Macro argv_item_t hides platform details to code using it. */ - #ifdef __VMS #define argv_item_t __char_ptr32 -#elif defined(_UNICODE) && !defined(UNDER_CE) +#elif defined(_UNICODE) #define argv_item_t wchar_t * #else #define argv_item_t char * #endif - /* * We use this ZERO_NULL to avoid picky compiler warnings, * when assigning a NULL pointer to a function pointer var. */ - #define ZERO_NULL 0 - #endif /* HEADER_CURL_SETUP_ONCE_H */ diff --git a/lib/curl_sha256.h b/lib/curl_sha256.h index caa5080b3f0f..99a87b290b1b 100644 --- a/lib/curl_sha256.h +++ b/lib/curl_sha256.h @@ -25,10 +25,11 @@ * ***************************************************************************/ +#include "curl_setup.h" + #if !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) || \ defined(USE_LIBSSH2) || defined(USE_SSL) -#include #include "curl_hmac.h" extern const struct HMAC_params Curl_HMAC_SHA256; diff --git a/lib/curl_sha512_256.c b/lib/curl_sha512_256.c index 7e9b223387e0..aff0ce0a4737 100644 --- a/lib/curl_sha512_256.c +++ b/lib/curl_sha512_256.c @@ -27,23 +27,20 @@ #if !defined(CURL_DISABLE_DIGEST_AUTH) && !defined(CURL_DISABLE_SHA512_256) #include "curl_sha512_256.h" -#include "curlx/warnless.h" /* The recommended order of the TLS backends: - * * OpenSSL - * * GnuTLS - * * wolfSSL - * * Schannel SSPI - * * mbedTLS - * * Rustls + * 1. OpenSSL + * 2. GnuTLS + * 3. wolfSSL + * 4. Schannel SSPI + * 5. mbedTLS + * 6. Rustls * Skip the backend if it does not support the required algorithm */ #ifdef USE_OPENSSL # include -# if (!defined(LIBRESSL_VERSION_NUMBER) && \ - OPENSSL_VERSION_NUMBER >= 0x10101000L) || \ - (defined(LIBRESSL_VERSION_NUMBER) && \ - LIBRESSL_VERSION_NUMBER >= 0x3080000fL) +# if !defined(LIBRESSL_VERSION_NUMBER) || \ + (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x3080000fL) # include # if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA512) # include @@ -67,14 +64,12 @@ (__NetBSD_Version__ >= 1099000000 && \ __NetBSD_Version__ < 1099001100) # define NEED_NETBSD_SHA512_256_WORKAROUND 1 -# include # endif # endif # endif # endif #endif /* USE_OPENSSL */ - #if !defined(HAS_SHA512_256_IMPLEMENTATION) && defined(USE_GNUTLS) # include # ifdef SHA512_256_DIGEST_SIZE @@ -111,7 +106,7 @@ typedef EVP_MD_CTX *Curl_sha512_256_ctx; */ static CURLcode Curl_sha512_256_init(void *context) { - Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context; + Curl_sha512_256_ctx * const ctx = (Curl_sha512_256_ctx *)context; *ctx = EVP_MD_CTX_create(); if(!*ctx) @@ -131,7 +126,6 @@ static CURLcode Curl_sha512_256_init(void *context) return CURLE_FAILED_INIT; } - /** * Process portion of bytes. * @@ -144,7 +138,7 @@ static CURLcode Curl_sha512_256_update(void *context, const unsigned char *data, size_t length) { - Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context; + Curl_sha512_256_ctx * const ctx = (Curl_sha512_256_ctx *)context; if(!EVP_DigestUpdate(*ctx, data, length)) return CURLE_SSL_CIPHER; @@ -152,7 +146,6 @@ static CURLcode Curl_sha512_256_update(void *context, return CURLE_OK; } - /** * Finalise SHA-512/256 calculation, return digest. * @@ -165,7 +158,7 @@ static CURLcode Curl_sha512_256_update(void *context, static CURLcode Curl_sha512_256_finish(unsigned char *digest, void *context) { CURLcode ret; - Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context; + Curl_sha512_256_ctx * const ctx = (Curl_sha512_256_ctx *)context; #ifdef NEED_NETBSD_SHA512_256_WORKAROUND /* Use a larger buffer to work around a bug in NetBSD: @@ -204,7 +197,7 @@ typedef struct sha512_256_ctx Curl_sha512_256_ctx; */ static CURLcode Curl_sha512_256_init(void *context) { - Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context; + Curl_sha512_256_ctx * const ctx = (Curl_sha512_256_ctx *)context; /* Check whether the header and this file use the same numbers */ DEBUGASSERT(CURL_SHA512_256_DIGEST_LENGTH == CURL_SHA512_256_DIGEST_SIZE); @@ -214,7 +207,6 @@ static CURLcode Curl_sha512_256_init(void *context) return CURLE_OK; } - /** * Process portion of bytes. * @@ -227,7 +219,7 @@ static CURLcode Curl_sha512_256_update(void *context, const unsigned char *data, size_t length) { - Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context; + Curl_sha512_256_ctx * const ctx = (Curl_sha512_256_ctx *)context; DEBUGASSERT((data != NULL) || (length == 0)); @@ -236,7 +228,6 @@ static CURLcode Curl_sha512_256_update(void *context, return CURLE_OK; } - /** * Finalise SHA-512/256 calculation, return digest. * @@ -245,10 +236,9 @@ static CURLcode Curl_sha512_256_update(void *context, # bytes * @return always CURLE_OK */ -static CURLcode Curl_sha512_256_finish(unsigned char *digest, - void *context) +static CURLcode Curl_sha512_256_finish(unsigned char *digest, void *context) { - Curl_sha512_256_ctx *const ctx = (Curl_sha512_256_ctx *)context; + Curl_sha512_256_ctx * const ctx = (Curl_sha512_256_ctx *)context; sha512_256_digest(ctx, (size_t)CURL_SHA512_256_DIGEST_SIZE, (uint8_t *)digest); @@ -288,32 +278,31 @@ static CURLcode Curl_sha512_256_finish(unsigned char *digest, /* Bits manipulation macros and functions. Can be moved to other headers to reuse. */ -#define CURL_GET_64BIT_BE(ptr) \ - ( ((curl_uint64_t)(((const unsigned char*)(ptr))[0]) << 56) | \ - ((curl_uint64_t)(((const unsigned char*)(ptr))[1]) << 48) | \ - ((curl_uint64_t)(((const unsigned char*)(ptr))[2]) << 40) | \ - ((curl_uint64_t)(((const unsigned char*)(ptr))[3]) << 32) | \ - ((curl_uint64_t)(((const unsigned char*)(ptr))[4]) << 24) | \ - ((curl_uint64_t)(((const unsigned char*)(ptr))[5]) << 16) | \ - ((curl_uint64_t)(((const unsigned char*)(ptr))[6]) << 8) | \ - (curl_uint64_t)(((const unsigned char*)(ptr))[7]) ) - -#define CURL_PUT_64BIT_BE(ptr,val) do { \ - ((unsigned char*)(ptr))[7]=(unsigned char)((curl_uint64_t)(val)); \ - ((unsigned char*)(ptr))[6]=(unsigned char)(((curl_uint64_t)(val)) >> 8); \ - ((unsigned char*)(ptr))[5]=(unsigned char)(((curl_uint64_t)(val)) >> 16); \ - ((unsigned char*)(ptr))[4]=(unsigned char)(((curl_uint64_t)(val)) >> 24); \ - ((unsigned char*)(ptr))[3]=(unsigned char)(((curl_uint64_t)(val)) >> 32); \ - ((unsigned char*)(ptr))[2]=(unsigned char)(((curl_uint64_t)(val)) >> 40); \ - ((unsigned char*)(ptr))[1]=(unsigned char)(((curl_uint64_t)(val)) >> 48); \ - ((unsigned char*)(ptr))[0]=(unsigned char)(((curl_uint64_t)(val)) >> 56); \ +#define CURL_GET_64BIT_BE(ptr) \ + (((uint64_t)(((const uint8_t *)(ptr))[0]) << 56) | \ + ((uint64_t)(((const uint8_t *)(ptr))[1]) << 48) | \ + ((uint64_t)(((const uint8_t *)(ptr))[2]) << 40) | \ + ((uint64_t)(((const uint8_t *)(ptr))[3]) << 32) | \ + ((uint64_t)(((const uint8_t *)(ptr))[4]) << 24) | \ + ((uint64_t)(((const uint8_t *)(ptr))[5]) << 16) | \ + ((uint64_t)(((const uint8_t *)(ptr))[6]) << 8) | \ + (uint64_t)(((const uint8_t *)(ptr))[7])) + +#define CURL_PUT_64BIT_BE(ptr,val) do { \ + ((uint8_t*)(ptr))[7] = (uint8_t) ((uint64_t)(val)); \ + ((uint8_t*)(ptr))[6] = (uint8_t)(((uint64_t)(val)) >> 8); \ + ((uint8_t*)(ptr))[5] = (uint8_t)(((uint64_t)(val)) >> 16); \ + ((uint8_t*)(ptr))[4] = (uint8_t)(((uint64_t)(val)) >> 24); \ + ((uint8_t*)(ptr))[3] = (uint8_t)(((uint64_t)(val)) >> 32); \ + ((uint8_t*)(ptr))[2] = (uint8_t)(((uint64_t)(val)) >> 40); \ + ((uint8_t*)(ptr))[1] = (uint8_t)(((uint64_t)(val)) >> 48); \ + ((uint8_t*)(ptr))[0] = (uint8_t)(((uint64_t)(val)) >> 56); \ } while(0) /* Defined as a function. The macro version may duplicate the binary code * size as each argument is used twice, so if any calculation is used * as an argument, the calculation could be done twice. */ -static CURL_FORCEINLINE curl_uint64_t Curl_rotr64(curl_uint64_t value, - unsigned int bits) +static CURL_FORCEINLINE uint64_t Curl_rotr64(uint64_t value, unsigned int bits) { bits %= 64; if(bits == 0) @@ -344,7 +333,7 @@ static CURL_FORCEINLINE curl_uint64_t Curl_rotr64(curl_uint64_t value, * Size of the SHA-512/256 resulting digest in words. * This is the final digest size, not intermediate hash. */ -#define SHA512_256_DIGEST_SIZE_WORDS (SHA512_256_HASH_SIZE_WORDS / 2) +#define SHA512_256_DIGEST_SIZE_WORDS (SHA512_256_HASH_SIZE_WORDS / 2) /** * Size of the SHA-512/256 resulting digest in bytes @@ -378,22 +367,22 @@ struct Curl_sha512_256ctx { * compilers may automatically use fast load/store instruction for big * endian data on little endian machine. */ - curl_uint64_t H[SHA512_256_HASH_SIZE_WORDS]; + uint64_t H[SHA512_256_HASH_SIZE_WORDS]; /** * SHA-512/256 input data buffer. The buffer is properly aligned. Smart * compilers may automatically use fast load/store instruction for big * endian data on little endian machine. */ - curl_uint64_t buffer[SHA512_256_BLOCK_SIZE_WORDS]; + uint64_t buffer[SHA512_256_BLOCK_SIZE_WORDS]; /** * The number of bytes, lower part */ - curl_uint64_t count; + uint64_t count; /** * The number of bits, high part. Unlike lower part, this counts the number * of bits, not bytes. */ - curl_uint64_t count_bits_hi; + uint64_t count_bits_hi; }; /** @@ -401,7 +390,6 @@ struct Curl_sha512_256ctx { */ typedef struct Curl_sha512_256ctx Curl_sha512_256_ctx; - /** * Initialise structure for SHA-512/256 calculation. * @@ -410,119 +398,117 @@ typedef struct Curl_sha512_256ctx Curl_sha512_256_ctx; */ static CURLcode Curl_sha512_256_init(void *context) { - struct Curl_sha512_256ctx *const ctx = (struct Curl_sha512_256ctx *)context; + struct Curl_sha512_256ctx * const ctx = (struct Curl_sha512_256ctx *)context; /* Check whether the header and this file use the same numbers */ DEBUGASSERT(CURL_SHA512_256_DIGEST_LENGTH == CURL_SHA512_256_DIGEST_SIZE); - DEBUGASSERT(sizeof(curl_uint64_t) == 8); + DEBUGASSERT(sizeof(uint64_t) == 8); /* Initial hash values, see FIPS PUB 180-4 section 5.3.6.2 */ /* Values generated by "IV Generation Function" as described in * section 5.3.6 */ - ctx->H[0] = CURL_UINT64_C(0x22312194FC2BF72C); - ctx->H[1] = CURL_UINT64_C(0x9F555FA3C84C64C2); - ctx->H[2] = CURL_UINT64_C(0x2393B86B6F53B151); - ctx->H[3] = CURL_UINT64_C(0x963877195940EABD); - ctx->H[4] = CURL_UINT64_C(0x96283EE2A88EFFE3); - ctx->H[5] = CURL_UINT64_C(0xBE5E1E2553863992); - ctx->H[6] = CURL_UINT64_C(0x2B0199FC2C85B8AA); - ctx->H[7] = CURL_UINT64_C(0x0EB72DDC81C52CA2); + ctx->H[0] = UINT64_C(0x22312194FC2BF72C); + ctx->H[1] = UINT64_C(0x9F555FA3C84C64C2); + ctx->H[2] = UINT64_C(0x2393B86B6F53B151); + ctx->H[3] = UINT64_C(0x963877195940EABD); + ctx->H[4] = UINT64_C(0x96283EE2A88EFFE3); + ctx->H[5] = UINT64_C(0xBE5E1E2553863992); + ctx->H[6] = UINT64_C(0x2B0199FC2C85B8AA); + ctx->H[7] = UINT64_C(0x0EB72DDC81C52CA2); /* Initialise number of bytes and high part of number of bits. */ - ctx->count = CURL_UINT64_C(0); - ctx->count_bits_hi = CURL_UINT64_C(0); + ctx->count = UINT64_C(0); + ctx->count_bits_hi = UINT64_C(0); return CURLE_OK; } - /** * Base of the SHA-512/256 transformation. * Gets a full 128 bytes block of data and updates hash values; * @param H hash values * @param data the data buffer with #CURL_SHA512_256_BLOCK_SIZE bytes block */ -static -void Curl_sha512_256_transform(curl_uint64_t H[SHA512_256_HASH_SIZE_WORDS], - const void *data) +static void Curl_sha512_256_transform(uint64_t H[SHA512_256_HASH_SIZE_WORDS], + const void *data) { /* Working variables, see FIPS PUB 180-4 section 6.7, 6.4. */ - curl_uint64_t a = H[0]; - curl_uint64_t b = H[1]; - curl_uint64_t c = H[2]; - curl_uint64_t d = H[3]; - curl_uint64_t e = H[4]; - curl_uint64_t f = H[5]; - curl_uint64_t g = H[6]; - curl_uint64_t h = H[7]; + uint64_t a = H[0]; + uint64_t b = H[1]; + uint64_t c = H[2]; + uint64_t d = H[3]; + uint64_t e = H[4]; + uint64_t f = H[5]; + uint64_t g = H[6]; + uint64_t h = H[7]; /* Data buffer, used as a cyclic buffer. See FIPS PUB 180-4 section 5.2.2, 6.7, 6.4. */ - curl_uint64_t W[16]; + uint64_t W[16]; /* 'Ch' and 'Maj' macro functions are defined with widely-used optimization. See FIPS PUB 180-4 formulae 4.8, 4.9. */ -#define Sha512_Ch(x,y,z) ( (z) ^ ((x) & ((y) ^ (z))) ) -#define Sha512_Maj(x,y,z) ( ((x) & (y)) ^ ((z) & ((x) ^ (y))) ) +#define Sha512_Ch(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define Sha512_Maj(x, y, z) (((x) & (y)) ^ ((z) & ((x) ^ (y)))) /* Four 'Sigma' macro functions. See FIPS PUB 180-4 formulae 4.10, 4.11, 4.12, 4.13. */ #define SIG0(x) \ - ( Curl_rotr64((x), 28) ^ Curl_rotr64((x), 34) ^ Curl_rotr64((x), 39) ) + (Curl_rotr64((x), 28) ^ Curl_rotr64((x), 34) ^ Curl_rotr64((x), 39)) #define SIG1(x) \ - ( Curl_rotr64((x), 14) ^ Curl_rotr64((x), 18) ^ Curl_rotr64((x), 41) ) + (Curl_rotr64((x), 14) ^ Curl_rotr64((x), 18) ^ Curl_rotr64((x), 41)) #define sig0(x) \ - ( Curl_rotr64((x), 1) ^ Curl_rotr64((x), 8) ^ ((x) >> 7) ) + (Curl_rotr64((x), 1) ^ Curl_rotr64((x), 8) ^ ((x) >> 7)) #define sig1(x) \ - ( Curl_rotr64((x), 19) ^ Curl_rotr64((x), 61) ^ ((x) >> 6) ) + (Curl_rotr64((x), 19) ^ Curl_rotr64((x), 61) ^ ((x) >> 6)) if(1) { unsigned int t; /* K constants array. See FIPS PUB 180-4 section 4.2.3 for K values. */ - static const curl_uint64_t K[80] = { - CURL_UINT64_C(0x428a2f98d728ae22), CURL_UINT64_C(0x7137449123ef65cd), - CURL_UINT64_C(0xb5c0fbcfec4d3b2f), CURL_UINT64_C(0xe9b5dba58189dbbc), - CURL_UINT64_C(0x3956c25bf348b538), CURL_UINT64_C(0x59f111f1b605d019), - CURL_UINT64_C(0x923f82a4af194f9b), CURL_UINT64_C(0xab1c5ed5da6d8118), - CURL_UINT64_C(0xd807aa98a3030242), CURL_UINT64_C(0x12835b0145706fbe), - CURL_UINT64_C(0x243185be4ee4b28c), CURL_UINT64_C(0x550c7dc3d5ffb4e2), - CURL_UINT64_C(0x72be5d74f27b896f), CURL_UINT64_C(0x80deb1fe3b1696b1), - CURL_UINT64_C(0x9bdc06a725c71235), CURL_UINT64_C(0xc19bf174cf692694), - CURL_UINT64_C(0xe49b69c19ef14ad2), CURL_UINT64_C(0xefbe4786384f25e3), - CURL_UINT64_C(0x0fc19dc68b8cd5b5), CURL_UINT64_C(0x240ca1cc77ac9c65), - CURL_UINT64_C(0x2de92c6f592b0275), CURL_UINT64_C(0x4a7484aa6ea6e483), - CURL_UINT64_C(0x5cb0a9dcbd41fbd4), CURL_UINT64_C(0x76f988da831153b5), - CURL_UINT64_C(0x983e5152ee66dfab), CURL_UINT64_C(0xa831c66d2db43210), - CURL_UINT64_C(0xb00327c898fb213f), CURL_UINT64_C(0xbf597fc7beef0ee4), - CURL_UINT64_C(0xc6e00bf33da88fc2), CURL_UINT64_C(0xd5a79147930aa725), - CURL_UINT64_C(0x06ca6351e003826f), CURL_UINT64_C(0x142929670a0e6e70), - CURL_UINT64_C(0x27b70a8546d22ffc), CURL_UINT64_C(0x2e1b21385c26c926), - CURL_UINT64_C(0x4d2c6dfc5ac42aed), CURL_UINT64_C(0x53380d139d95b3df), - CURL_UINT64_C(0x650a73548baf63de), CURL_UINT64_C(0x766a0abb3c77b2a8), - CURL_UINT64_C(0x81c2c92e47edaee6), CURL_UINT64_C(0x92722c851482353b), - CURL_UINT64_C(0xa2bfe8a14cf10364), CURL_UINT64_C(0xa81a664bbc423001), - CURL_UINT64_C(0xc24b8b70d0f89791), CURL_UINT64_C(0xc76c51a30654be30), - CURL_UINT64_C(0xd192e819d6ef5218), CURL_UINT64_C(0xd69906245565a910), - CURL_UINT64_C(0xf40e35855771202a), CURL_UINT64_C(0x106aa07032bbd1b8), - CURL_UINT64_C(0x19a4c116b8d2d0c8), CURL_UINT64_C(0x1e376c085141ab53), - CURL_UINT64_C(0x2748774cdf8eeb99), CURL_UINT64_C(0x34b0bcb5e19b48a8), - CURL_UINT64_C(0x391c0cb3c5c95a63), CURL_UINT64_C(0x4ed8aa4ae3418acb), - CURL_UINT64_C(0x5b9cca4f7763e373), CURL_UINT64_C(0x682e6ff3d6b2b8a3), - CURL_UINT64_C(0x748f82ee5defb2fc), CURL_UINT64_C(0x78a5636f43172f60), - CURL_UINT64_C(0x84c87814a1f0ab72), CURL_UINT64_C(0x8cc702081a6439ec), - CURL_UINT64_C(0x90befffa23631e28), CURL_UINT64_C(0xa4506cebde82bde9), - CURL_UINT64_C(0xbef9a3f7b2c67915), CURL_UINT64_C(0xc67178f2e372532b), - CURL_UINT64_C(0xca273eceea26619c), CURL_UINT64_C(0xd186b8c721c0c207), - CURL_UINT64_C(0xeada7dd6cde0eb1e), CURL_UINT64_C(0xf57d4f7fee6ed178), - CURL_UINT64_C(0x06f067aa72176fba), CURL_UINT64_C(0x0a637dc5a2c898a6), - CURL_UINT64_C(0x113f9804bef90dae), CURL_UINT64_C(0x1b710b35131c471b), - CURL_UINT64_C(0x28db77f523047d84), CURL_UINT64_C(0x32caab7b40c72493), - CURL_UINT64_C(0x3c9ebe0a15c9bebc), CURL_UINT64_C(0x431d67c49c100d4c), - CURL_UINT64_C(0x4cc5d4becb3e42b6), CURL_UINT64_C(0x597f299cfc657e2a), - CURL_UINT64_C(0x5fcb6fab3ad6faec), CURL_UINT64_C(0x6c44198c4a475817) + static const uint64_t K[80] = { + UINT64_C(0x428a2f98d728ae22), UINT64_C(0x7137449123ef65cd), + UINT64_C(0xb5c0fbcfec4d3b2f), UINT64_C(0xe9b5dba58189dbbc), + UINT64_C(0x3956c25bf348b538), UINT64_C(0x59f111f1b605d019), + UINT64_C(0x923f82a4af194f9b), UINT64_C(0xab1c5ed5da6d8118), + UINT64_C(0xd807aa98a3030242), UINT64_C(0x12835b0145706fbe), + UINT64_C(0x243185be4ee4b28c), UINT64_C(0x550c7dc3d5ffb4e2), + UINT64_C(0x72be5d74f27b896f), UINT64_C(0x80deb1fe3b1696b1), + UINT64_C(0x9bdc06a725c71235), UINT64_C(0xc19bf174cf692694), + UINT64_C(0xe49b69c19ef14ad2), UINT64_C(0xefbe4786384f25e3), + UINT64_C(0x0fc19dc68b8cd5b5), UINT64_C(0x240ca1cc77ac9c65), + UINT64_C(0x2de92c6f592b0275), UINT64_C(0x4a7484aa6ea6e483), + UINT64_C(0x5cb0a9dcbd41fbd4), UINT64_C(0x76f988da831153b5), + UINT64_C(0x983e5152ee66dfab), UINT64_C(0xa831c66d2db43210), + UINT64_C(0xb00327c898fb213f), UINT64_C(0xbf597fc7beef0ee4), + UINT64_C(0xc6e00bf33da88fc2), UINT64_C(0xd5a79147930aa725), + UINT64_C(0x06ca6351e003826f), UINT64_C(0x142929670a0e6e70), + UINT64_C(0x27b70a8546d22ffc), UINT64_C(0x2e1b21385c26c926), + UINT64_C(0x4d2c6dfc5ac42aed), UINT64_C(0x53380d139d95b3df), + UINT64_C(0x650a73548baf63de), UINT64_C(0x766a0abb3c77b2a8), + UINT64_C(0x81c2c92e47edaee6), UINT64_C(0x92722c851482353b), + UINT64_C(0xa2bfe8a14cf10364), UINT64_C(0xa81a664bbc423001), + UINT64_C(0xc24b8b70d0f89791), UINT64_C(0xc76c51a30654be30), + UINT64_C(0xd192e819d6ef5218), UINT64_C(0xd69906245565a910), + UINT64_C(0xf40e35855771202a), UINT64_C(0x106aa07032bbd1b8), + UINT64_C(0x19a4c116b8d2d0c8), UINT64_C(0x1e376c085141ab53), + UINT64_C(0x2748774cdf8eeb99), UINT64_C(0x34b0bcb5e19b48a8), + UINT64_C(0x391c0cb3c5c95a63), UINT64_C(0x4ed8aa4ae3418acb), + UINT64_C(0x5b9cca4f7763e373), UINT64_C(0x682e6ff3d6b2b8a3), + UINT64_C(0x748f82ee5defb2fc), UINT64_C(0x78a5636f43172f60), + UINT64_C(0x84c87814a1f0ab72), UINT64_C(0x8cc702081a6439ec), + UINT64_C(0x90befffa23631e28), UINT64_C(0xa4506cebde82bde9), + UINT64_C(0xbef9a3f7b2c67915), UINT64_C(0xc67178f2e372532b), + UINT64_C(0xca273eceea26619c), UINT64_C(0xd186b8c721c0c207), + UINT64_C(0xeada7dd6cde0eb1e), UINT64_C(0xf57d4f7fee6ed178), + UINT64_C(0x06f067aa72176fba), UINT64_C(0x0a637dc5a2c898a6), + UINT64_C(0x113f9804bef90dae), UINT64_C(0x1b710b35131c471b), + UINT64_C(0x28db77f523047d84), UINT64_C(0x32caab7b40c72493), + UINT64_C(0x3c9ebe0a15c9bebc), UINT64_C(0x431d67c49c100d4c), + UINT64_C(0x4cc5d4becb3e42b6), UINT64_C(0x597f299cfc657e2a), + UINT64_C(0x5fcb6fab3ad6faec), UINT64_C(0x6c44198c4a475817) }; /* One step of SHA-512/256 computation, @@ -535,38 +521,41 @@ void Curl_sha512_256_transform(curl_uint64_t H[SHA512_256_HASH_SIZE_WORDS], * Note: 'wt' must be used exactly one time in this macro as macro for 'wt' calculation may change other data as well every time when used. */ -#define SHA2STEP64(vA,vB,vC,vD,vE,vF,vG,vH,kt,wt) do { \ - (vD) += ((vH) += SIG1((vE)) + Sha512_Ch((vE),(vF),(vG)) + (kt) + (wt)); \ - (vH) += SIG0((vA)) + Sha512_Maj((vA),(vB),(vC)); } while (0) +#define SHA2STEP64(vA, vB, vC, vD, vE, vF, vG, vH, kt, wt) \ + do { \ + (vD) += ((vH) += SIG1((vE)) + Sha512_Ch((vE), (vF), (vG)) + (kt) + (wt)); \ + (vH) += SIG0((vA)) + Sha512_Maj((vA), (vB), (vC)); \ + } while(0) /* One step of SHA-512/256 computation with working variables rotation, see FIPS PUB 180-4 section 6.4.2 step 3. This macro version reassigns all working variables on each step. */ -#define SHA2STEP64RV(vA,vB,vC,vD,vE,vF,vG,vH,kt,wt) do { \ - curl_uint64_t tmp_h_ = (vH); \ - SHA2STEP64((vA),(vB),(vC),(vD),(vE),(vF),(vG),tmp_h_,(kt),(wt)); \ - (vH) = (vG); \ - (vG) = (vF); \ - (vF) = (vE); \ - (vE) = (vD); \ - (vD) = (vC); \ - (vC) = (vB); \ - (vB) = (vA); \ - (vA) = tmp_h_; } while(0) +#define SHA2STEP64RV(vA, vB, vC, vD, vE, vF, vG, vH, kt, wt) \ + do { \ + uint64_t tmp_h_ = (vH); \ + SHA2STEP64((vA), (vB), (vC), (vD), (vE), (vF), (vG), tmp_h_, (kt), (wt)); \ + (vH) = (vG); \ + (vG) = (vF); \ + (vF) = (vE); \ + (vE) = (vD); \ + (vD) = (vC); \ + (vC) = (vB); \ + (vB) = (vA); \ + (vA) = tmp_h_; \ + } while(0) /* Get value of W(t) from input data buffer for 0 <= t <= 15, See FIPS PUB 180-4 section 6.2. Input data must be read in big-endian bytes order, see FIPS PUB 180-4 section 3.1.2. */ -#define SHA512_GET_W_FROM_DATA(buf,t) \ - CURL_GET_64BIT_BE( \ - ((const unsigned char*) (buf)) + (t) * SHA512_256_BYTES_IN_WORD) +#define SHA512_GET_W_FROM_DATA(buf, t) \ + CURL_GET_64BIT_BE(((const uint8_t *)(buf)) + (t) * SHA512_256_BYTES_IN_WORD) /* During first 16 steps, before making any calculation on each step, the W element is read from the input data buffer as a big-endian value and stored in the array of W elements. */ for(t = 0; t < 16; ++t) { - SHA2STEP64RV(a, b, c, d, e, f, g, h, K[t], \ + SHA2STEP64RV(a, b, c, d, e, f, g, h, K[t], W[t] = SHA512_GET_W_FROM_DATA(data, t)); } @@ -575,15 +564,15 @@ void Curl_sha512_256_transform(curl_uint64_t H[SHA512_256_HASH_SIZE_WORDS], As only the last 16 'W' are used in calculations, it is possible to use 16 elements array of W as a cyclic buffer. Note: ((t-16) & 15) have same value as (t & 15) */ -#define Wgen(w,t) \ - (curl_uint64_t)( (w)[(t - 16) & 15] + sig1((w)[((t) - 2) & 15]) \ - + (w)[((t) - 7) & 15] + sig0((w)[((t) - 15) & 15]) ) +#define Wgen(w, t) \ + (uint64_t)((w)[((t) - 16) & 15] + sig1((w)[((t) - 2) & 15]) + \ + (w)[((t) - 7) & 15] + sig0((w)[((t) - 15) & 15])) /* During the last 64 steps, before making any calculation on each step, current W element is generated from other W elements of the cyclic buffer and the generated value is stored back in the cyclic buffer. */ for(t = 16; t < 80; ++t) { - SHA2STEP64RV(a, b, c, d, e, f, g, h, K[t], \ + SHA2STEP64RV(a, b, c, d, e, f, g, h, K[t], W[t & 15] = Wgen(W, t)); } } @@ -600,7 +589,6 @@ void Curl_sha512_256_transform(curl_uint64_t H[SHA512_256_HASH_SIZE_WORDS], H[7] += h; } - /** * Process portion of bytes. * @@ -614,9 +602,9 @@ static CURLcode Curl_sha512_256_update(void *context, size_t length) { unsigned int bytes_have; /**< Number of bytes in the context buffer */ - struct Curl_sha512_256ctx *const ctx = (struct Curl_sha512_256ctx *)context; + struct Curl_sha512_256ctx * const ctx = (struct Curl_sha512_256ctx *)context; /* the void pointer here is required to mute Intel compiler warning */ - void *const ctx_buf = ctx->buffer; + void * const ctx_buf = ctx->buffer; DEBUGASSERT((data != NULL) || (length == 0)); @@ -625,21 +613,19 @@ static CURLcode Curl_sha512_256_update(void *context, /* Note: (count & (CURL_SHA512_256_BLOCK_SIZE-1)) equals (count % CURL_SHA512_256_BLOCK_SIZE) for this block size. */ - bytes_have = (unsigned int) (ctx->count & (CURL_SHA512_256_BLOCK_SIZE - 1)); + bytes_have = (unsigned int)(ctx->count & (CURL_SHA512_256_BLOCK_SIZE - 1)); ctx->count += length; if(length > ctx->count) ctx->count_bits_hi += 1U << 3; /* Value wrap */ ctx->count_bits_hi += ctx->count >> 61; - ctx->count &= CURL_UINT64_C(0x1FFFFFFFFFFFFFFF); + ctx->count &= UINT64_C(0x1FFFFFFFFFFFFFFF); if(bytes_have) { unsigned int bytes_left = CURL_SHA512_256_BLOCK_SIZE - bytes_have; if(length >= bytes_left) { /* Combine new data with data in the buffer and process the full block. */ - memcpy(((unsigned char *) ctx_buf) + bytes_have, - data, - bytes_left); + memcpy(((unsigned char *)ctx_buf) + bytes_have, data, bytes_left); data += bytes_left; length -= bytes_left; Curl_sha512_256_transform(ctx->H, ctx->buffer); @@ -658,13 +644,12 @@ static CURLcode Curl_sha512_256_update(void *context, if(length) { /* Copy incomplete block of new data (if any) to the buffer. */ - memcpy(((unsigned char *) ctx_buf) + bytes_have, data, length); + memcpy(((unsigned char *)ctx_buf) + bytes_have, data, length); } return CURLE_OK; } - /** * Size of "length" insertion in bits. * See FIPS PUB 180-4 section 5.1.2. @@ -686,11 +671,11 @@ static CURLcode Curl_sha512_256_update(void *context, */ static CURLcode Curl_sha512_256_finish(unsigned char *digest, void *context) { - struct Curl_sha512_256ctx *const ctx = (struct Curl_sha512_256ctx *)context; - curl_uint64_t num_bits; /**< Number of processed bits */ + struct Curl_sha512_256ctx * const ctx = (struct Curl_sha512_256ctx *)context; + uint64_t num_bits; /**< Number of processed bits */ unsigned int bytes_have; /**< Number of bytes in the context buffer */ /* the void pointer here is required to mute Intel compiler warning */ - void *const ctx_buf = ctx->buffer; + void * const ctx_buf = ctx->buffer; /* Memorise the number of processed bits. The padding and other data added here during the postprocessing must @@ -699,7 +684,7 @@ static CURLcode Curl_sha512_256_finish(unsigned char *digest, void *context) /* Note: (count & (CURL_SHA512_256_BLOCK_SIZE-1)) equals (count % CURL_SHA512_256_BLOCK_SIZE) for this block size. */ - bytes_have = (unsigned int) (ctx->count & (CURL_SHA512_256_BLOCK_SIZE - 1)); + bytes_have = (unsigned int)(ctx->count & (CURL_SHA512_256_BLOCK_SIZE - 1)); /* Input data must be padded with a single bit "1", then with zeros and the finally the length of data in bits must be added as the final bytes @@ -711,13 +696,13 @@ static CURLcode Curl_sha512_256_finish(unsigned char *digest, void *context) predefined (0x80). */ /* Buffer always have space at least for one byte (as full buffers are processed when formed). */ - ((unsigned char *) ctx_buf)[bytes_have++] = 0x80U; + ((unsigned char *)ctx_buf)[bytes_have++] = 0x80U; if(CURL_SHA512_256_BLOCK_SIZE - bytes_have < SHA512_256_SIZE_OF_LEN_ADD) { /* No space in the current block to put the total length of message. Pad the current block with zeros and process it. */ if(bytes_have < CURL_SHA512_256_BLOCK_SIZE) - memset(((unsigned char *) ctx_buf) + bytes_have, 0, + memset(((unsigned char *)ctx_buf) + bytes_have, 0, CURL_SHA512_256_BLOCK_SIZE - bytes_have); /* Process the full block. */ Curl_sha512_256_transform(ctx->H, ctx->buffer); @@ -726,17 +711,17 @@ static CURLcode Curl_sha512_256_finish(unsigned char *digest, void *context) } /* Pad the rest of the buffer with zeros. */ - memset(((unsigned char *) ctx_buf) + bytes_have, 0, + memset(((unsigned char *)ctx_buf) + bytes_have, 0, CURL_SHA512_256_BLOCK_SIZE - SHA512_256_SIZE_OF_LEN_ADD - bytes_have); /* Put high part of number of bits in processed message and then lower part of number of bits as big-endian values. See FIPS PUB 180-4 section 5.1.2. */ /* Note: the target location is predefined and buffer is always aligned */ - CURL_PUT_64BIT_BE(((unsigned char *) ctx_buf) \ + CURL_PUT_64BIT_BE(((unsigned char *)ctx_buf) \ + CURL_SHA512_256_BLOCK_SIZE \ - SHA512_256_SIZE_OF_LEN_ADD, \ ctx->count_bits_hi); - CURL_PUT_64BIT_BE(((unsigned char *) ctx_buf) \ + CURL_PUT_64BIT_BE(((unsigned char *)ctx_buf) \ + CURL_SHA512_256_BLOCK_SIZE \ - SHA512_256_SIZE_OF_LEN_ADD \ + SHA512_256_BYTES_IN_WORD, \ @@ -760,7 +745,6 @@ static CURLcode Curl_sha512_256_finish(unsigned char *digest, void *context) #endif /* Local SHA-512/256 code */ - /** * Compute SHA-512/256 hash for the given data in one function call * @param[out] output the pointer to put the hash @@ -778,7 +762,7 @@ CURLcode Curl_sha512_256it(unsigned char *output, const unsigned char *input, if(res != CURLE_OK) return res; - res = Curl_sha512_256_update(&ctx, (const void *) input, input_size); + res = Curl_sha512_256_update(&ctx, (const void *)input, input_size); if(res != CURLE_OK) { (void)Curl_sha512_256_finish(output, &ctx); diff --git a/lib/curl_sha512_256.h b/lib/curl_sha512_256.h index a84e77bc3038..0efcb27f3bff 100644 --- a/lib/curl_sha512_256.h +++ b/lib/curl_sha512_256.h @@ -24,9 +24,10 @@ * ***************************************************************************/ +#include "curl_setup.h" + #if !defined(CURL_DISABLE_DIGEST_AUTH) && !defined(CURL_DISABLE_SHA512_256) -#include #include "curl_hmac.h" #define CURL_HAVE_SHA512_256 @@ -35,9 +36,8 @@ extern const struct HMAC_params Curl_HMAC_SHA512_256[1]; #define CURL_SHA512_256_DIGEST_LENGTH 32 -CURLcode -Curl_sha512_256it(unsigned char *output, const unsigned char *input, - size_t input_size); +CURLcode Curl_sha512_256it(unsigned char *output, const unsigned char *input, + size_t input_size); #endif /* !CURL_DISABLE_DIGEST_AUTH && !CURL_DISABLE_SHA512_256 */ diff --git a/lib/share.c b/lib/curl_share.c similarity index 90% rename from lib/share.c rename to lib/curl_share.c index 711622a170a2..60ea78bf7fc0 100644 --- a/lib/share.c +++ b/lib/curl_share.c @@ -24,31 +24,24 @@ #include "curl_setup.h" -#include #include "urldata.h" #include "connect.h" -#include "share.h" -#include "psl.h" +#include "curl_share.h" #include "vtls/vtls.h" #include "vtls/vtls_scache.h" #include "hsts.h" #include "url.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - -CURLSH * -curl_share_init(void) +CURLSH *curl_share_init(void) { - struct Curl_share *share = calloc(1, sizeof(struct Curl_share)); + struct Curl_share *share = curlx_calloc(1, sizeof(struct Curl_share)); if(share) { share->magic = CURL_GOOD_SHARE; share->specifier |= (1 << CURL_LOCK_DATA_SHARE); Curl_dnscache_init(&share->dnscache, 23); share->admin = curl_easy_init(); if(!share->admin) { - free(share); + curlx_free(share); return NULL; } /* admin handles have mid 0 */ @@ -64,8 +57,7 @@ curl_share_init(void) } #undef curl_share_setopt -CURLSHcode -curl_share_setopt(CURLSH *sh, CURLSHoption option, ...) +CURLSHcode curl_share_setopt(CURLSH *sh, CURLSHoption option, ...) { va_list param; int type; @@ -97,7 +89,7 @@ curl_share_setopt(CURLSH *sh, CURLSHoption option, ...) case CURL_LOCK_DATA_COOKIE: #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) if(!share->cookies) { - share->cookies = Curl_cookie_init(NULL, NULL, NULL, TRUE); + share->cookies = Curl_cookie_init(); if(!share->cookies) res = CURLSHE_NOMEM; } @@ -228,8 +220,7 @@ curl_share_setopt(CURLSH *sh, CURLSHoption option, ...) return res; } -CURLSHcode -curl_share_cleanup(CURLSH *sh) +CURLSHcode curl_share_cleanup(CURLSH *sh) { struct Curl_share *share = sh; if(!GOOD_SHARE_HANDLE(share)) @@ -272,15 +263,13 @@ curl_share_cleanup(CURLSH *sh) if(share->unlockfunc) share->unlockfunc(NULL, CURL_LOCK_DATA_SHARE, share->clientdata); share->magic = 0; - free(share); + curlx_free(share); return CURLSHE_OK; } - -CURLSHcode -Curl_share_lock(struct Curl_easy *data, curl_lock_data type, - curl_lock_access accesstype) +CURLSHcode Curl_share_lock(struct Curl_easy *data, curl_lock_data type, + curl_lock_access accesstype) { struct Curl_share *share = data->share; @@ -296,8 +285,7 @@ Curl_share_lock(struct Curl_easy *data, curl_lock_data type, return CURLSHE_OK; } -CURLSHcode -Curl_share_unlock(struct Curl_easy *data, curl_lock_data type) +CURLSHcode Curl_share_unlock(struct Curl_easy *data, curl_lock_data type) { struct Curl_share *share = data->share; @@ -306,7 +294,7 @@ Curl_share_unlock(struct Curl_easy *data, curl_lock_data type) if(share->specifier & (unsigned int)(1 << type)) { if(share->unlockfunc) /* only call this if set! */ - share->unlockfunc (data, type, share->clientdata); + share->unlockfunc(data, type, share->clientdata); } return CURLSHE_OK; diff --git a/lib/share.h b/lib/curl_share.h similarity index 93% rename from lib/share.h rename to lib/curl_share.h index 974c99dc204b..25d67ce1d92e 100644 --- a/lib/share.h +++ b/lib/curl_share.h @@ -25,7 +25,7 @@ ***************************************************************************/ #include "curl_setup.h" -#include + #include "cookie.h" #include "psl.h" #include "urldata.h" @@ -38,7 +38,7 @@ struct Curl_ssl_scache; #define GOOD_SHARE_HANDLE(x) ((x) && (x)->magic == CURL_GOOD_SHARE) #define CURL_SHARE_KEEP_CONNECT(s) \ - ((s) && ((s)->specifier & (1<< CURL_LOCK_DATA_CONNECT))) + ((s) && ((s)->specifier & (1 << CURL_LOCK_DATA_CONNECT))) /* this struct is libcurl-private, do not export details */ struct Curl_share { @@ -71,8 +71,8 @@ CURLSHcode Curl_share_lock(struct Curl_easy *, curl_lock_data, CURLSHcode Curl_share_unlock(struct Curl_easy *, curl_lock_data); /* convenience macro to check if this handle is using a shared SSL spool */ -#define CURL_SHARE_ssl_scache(data) (data->share && \ +#define CURL_SHARE_ssl_scache(data) (data->share && \ (data->share->specifier & \ - (1< #include "curl_sspi.h" #include "strdup.h" #include "curlx/multibyte.h" -#include "system_win32.h" -#include "curlx/warnless.h" - -/* The last #include files should be: */ -#include "curl_memory.h" -#include "memdebug.h" /* Pointer to SSPI dispatch table */ PSecurityFunctionTable Curl_pSecFn = NULL; @@ -62,11 +55,7 @@ CURLcode Curl_sspi_global_init(void) /* If security interface is not yet initialized try to do this */ if(!Curl_pSecFn) { /* Get pointer to Security Service Provider Interface dispatch table */ -#ifdef __MINGW32CE__ - Curl_pSecFn = InitSecurityInterfaceW(); -#else Curl_pSecFn = InitSecurityInterface(); -#endif if(!Curl_pSecFn) return CURLE_FAILED_INIT; } @@ -138,43 +127,54 @@ CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp, } /* Setup the identity's user and length */ - dup_user.tchar_ptr = Curl_tcsdup(user.tchar_ptr); + dup_user.tchar_ptr = curlx_tcsdup(user.tchar_ptr); if(!dup_user.tchar_ptr) { - curlx_unicodefree(useranddomain.tchar_ptr); + curlx_free(useranddomain.tchar_ptr); return CURLE_OUT_OF_MEMORY; } - identity->User = dup_user.tbyte_ptr; - identity->UserLength = curlx_uztoul(_tcslen(dup_user.tchar_ptr)); - dup_user.tchar_ptr = NULL; /* Setup the identity's domain and length */ - dup_domain.tchar_ptr = malloc(sizeof(TCHAR) * (domlen + 1)); + dup_domain.tchar_ptr = curlx_malloc(sizeof(TCHAR) * (domlen + 1)); if(!dup_domain.tchar_ptr) { - curlx_unicodefree(useranddomain.tchar_ptr); + curlx_free(dup_user.tchar_ptr); + curlx_free(useranddomain.tchar_ptr); + return CURLE_OUT_OF_MEMORY; + } + if(_tcsncpy_s(dup_domain.tchar_ptr, domlen + 1, domain.tchar_ptr, domlen)) { + curlx_free(dup_user.tchar_ptr); + curlx_free(dup_domain.tchar_ptr); + curlx_free(useranddomain.tchar_ptr); return CURLE_OUT_OF_MEMORY; } - _tcsncpy(dup_domain.tchar_ptr, domain.tchar_ptr, domlen); - *(dup_domain.tchar_ptr + domlen) = TEXT('\0'); - identity->Domain = dup_domain.tbyte_ptr; - identity->DomainLength = curlx_uztoul(domlen); - dup_domain.tchar_ptr = NULL; - curlx_unicodefree(useranddomain.tchar_ptr); + curlx_free(useranddomain.tchar_ptr); /* Setup the identity's password and length */ passwd.tchar_ptr = curlx_convert_UTF8_to_tchar(passwdp); - if(!passwd.tchar_ptr) + if(!passwd.tchar_ptr) { + curlx_free(dup_user.tchar_ptr); + curlx_free(dup_domain.tchar_ptr); return CURLE_OUT_OF_MEMORY; - dup_passwd.tchar_ptr = Curl_tcsdup(passwd.tchar_ptr); + } + dup_passwd.tchar_ptr = curlx_tcsdup(passwd.tchar_ptr); if(!dup_passwd.tchar_ptr) { - curlx_unicodefree(passwd.tchar_ptr); + curlx_free(dup_user.tchar_ptr); + curlx_free(dup_domain.tchar_ptr); + curlx_free(passwd.tchar_ptr); return CURLE_OUT_OF_MEMORY; } identity->Password = dup_passwd.tbyte_ptr; identity->PasswordLength = curlx_uztoul(_tcslen(dup_passwd.tchar_ptr)); dup_passwd.tchar_ptr = NULL; - curlx_unicodefree(passwd.tchar_ptr); + curlx_free(passwd.tchar_ptr); + + identity->User = dup_user.tbyte_ptr; + identity->UserLength = curlx_uztoul(_tcslen(dup_user.tchar_ptr)); + dup_user.tchar_ptr = NULL; + identity->Domain = dup_domain.tbyte_ptr; + identity->DomainLength = curlx_uztoul(domlen); + dup_domain.tchar_ptr = NULL; /* Setup the identity's flags */ identity->Flags = (unsigned long) diff --git a/lib/curl_sspi.h b/lib/curl_sspi.h index 8ecd81fdea14..46dc6faaa204 100644 --- a/lib/curl_sspi.h +++ b/lib/curl_sspi.h @@ -28,8 +28,6 @@ #ifdef USE_WINDOWS_SSPI -#include - /* * When including the following three headers, it is mandatory to define either * SECURITY_WIN32 or SECURITY_KERNEL, indicating who is compiling the code. @@ -70,225 +68,6 @@ extern PSecurityFunctionTable Curl_pSecFn; #define ISC_REQ_USE_HTTP_STYLE 0x01000000 #endif -#ifdef __MINGW32CE__ -#ifndef ISC_RET_REPLAY_DETECT -#define ISC_RET_REPLAY_DETECT 0x00000004 -#endif -#ifndef ISC_RET_SEQUENCE_DETECT -#define ISC_RET_SEQUENCE_DETECT 0x00000008 -#endif -#ifndef ISC_RET_CONFIDENTIALITY -#define ISC_RET_CONFIDENTIALITY 0x00000010 -#endif -#ifndef ISC_RET_ALLOCATED_MEMORY -#define ISC_RET_ALLOCATED_MEMORY 0x00000100 -#endif -#ifndef ISC_RET_STREAM -#define ISC_RET_STREAM 0x00008000 -#endif - -#ifndef SEC_E_INSUFFICIENT_MEMORY -#define SEC_E_INSUFFICIENT_MEMORY ((HRESULT)0x80090300L) -#endif -#ifndef SEC_E_INVALID_HANDLE -#define SEC_E_INVALID_HANDLE ((HRESULT)0x80090301L) -#endif -#ifndef SEC_E_UNSUPPORTED_FUNCTION -#define SEC_E_UNSUPPORTED_FUNCTION ((HRESULT)0x80090302L) -#endif -#ifndef SEC_E_TARGET_UNKNOWN -#define SEC_E_TARGET_UNKNOWN ((HRESULT)0x80090303L) -#endif -#ifndef SEC_E_INTERNAL_ERROR -#define SEC_E_INTERNAL_ERROR ((HRESULT)0x80090304L) -#endif -#ifndef SEC_E_SECPKG_NOT_FOUND -#define SEC_E_SECPKG_NOT_FOUND ((HRESULT)0x80090305L) -#endif -#ifndef SEC_E_NOT_OWNER -#define SEC_E_NOT_OWNER ((HRESULT)0x80090306L) -#endif -#ifndef SEC_E_CANNOT_INSTALL -#define SEC_E_CANNOT_INSTALL ((HRESULT)0x80090307L) -#endif -#ifndef SEC_E_INVALID_TOKEN -#define SEC_E_INVALID_TOKEN ((HRESULT)0x80090308L) -#endif -#ifndef SEC_E_CANNOT_PACK -#define SEC_E_CANNOT_PACK ((HRESULT)0x80090309L) -#endif -#ifndef SEC_E_QOP_NOT_SUPPORTED -#define SEC_E_QOP_NOT_SUPPORTED ((HRESULT)0x8009030AL) -#endif -#ifndef SEC_E_NO_IMPERSONATION -#define SEC_E_NO_IMPERSONATION ((HRESULT)0x8009030BL) -#endif -#ifndef SEC_E_LOGON_DENIED -#define SEC_E_LOGON_DENIED ((HRESULT)0x8009030CL) -#endif -#ifndef SEC_E_UNKNOWN_CREDENTIALS -#define SEC_E_UNKNOWN_CREDENTIALS ((HRESULT)0x8009030DL) -#endif -#ifndef SEC_E_NO_CREDENTIALS -#define SEC_E_NO_CREDENTIALS ((HRESULT)0x8009030EL) -#endif -#ifndef SEC_E_MESSAGE_ALTERED -#define SEC_E_MESSAGE_ALTERED ((HRESULT)0x8009030FL) -#endif -#ifndef SEC_E_OUT_OF_SEQUENCE -#define SEC_E_OUT_OF_SEQUENCE ((HRESULT)0x80090310L) -#endif -#ifndef SEC_E_NO_AUTHENTICATING_AUTHORITY -#define SEC_E_NO_AUTHENTICATING_AUTHORITY ((HRESULT)0x80090311L) -#endif -#ifndef SEC_E_BAD_PKGID -#define SEC_E_BAD_PKGID ((HRESULT)0x80090316L) -#endif -#ifndef SEC_E_CONTEXT_EXPIRED -#define SEC_E_CONTEXT_EXPIRED ((HRESULT)0x80090317L) -#endif -#ifndef SEC_E_INCOMPLETE_MESSAGE -#define SEC_E_INCOMPLETE_MESSAGE ((HRESULT)0x80090318L) -#endif -#ifndef SEC_E_INCOMPLETE_CREDENTIALS -#define SEC_E_INCOMPLETE_CREDENTIALS ((HRESULT)0x80090320L) -#endif -#ifndef SEC_E_BUFFER_TOO_SMALL -#define SEC_E_BUFFER_TOO_SMALL ((HRESULT)0x80090321L) -#endif -#ifndef SEC_E_WRONG_PRINCIPAL -#define SEC_E_WRONG_PRINCIPAL ((HRESULT)0x80090322L) -#endif -#ifndef SEC_E_TIME_SKEW -#define SEC_E_TIME_SKEW ((HRESULT)0x80090324L) -#endif -#ifndef SEC_E_UNTRUSTED_ROOT -#define SEC_E_UNTRUSTED_ROOT ((HRESULT)0x80090325L) -#endif -#ifndef SEC_E_ILLEGAL_MESSAGE -#define SEC_E_ILLEGAL_MESSAGE ((HRESULT)0x80090326L) -#endif -#ifndef SEC_E_CERT_UNKNOWN -#define SEC_E_CERT_UNKNOWN ((HRESULT)0x80090327L) -#endif -#ifndef SEC_E_CERT_EXPIRED -#define SEC_E_CERT_EXPIRED ((HRESULT)0x80090328L) -#endif -#ifndef SEC_E_ENCRYPT_FAILURE -#define SEC_E_ENCRYPT_FAILURE ((HRESULT)0x80090329L) -#endif -#ifndef SEC_E_DECRYPT_FAILURE -#define SEC_E_DECRYPT_FAILURE ((HRESULT)0x80090330L) -#endif -#ifndef SEC_E_ALGORITHM_MISMATCH -#define SEC_E_ALGORITHM_MISMATCH ((HRESULT)0x80090331L) -#endif -#ifndef SEC_E_SECURITY_QOS_FAILED -#define SEC_E_SECURITY_QOS_FAILED ((HRESULT)0x80090332L) -#endif -#ifndef SEC_E_UNFINISHED_CONTEXT_DELETED -#define SEC_E_UNFINISHED_CONTEXT_DELETED ((HRESULT)0x80090333L) -#endif -#ifndef SEC_E_NO_TGT_REPLY -#define SEC_E_NO_TGT_REPLY ((HRESULT)0x80090334L) -#endif -#ifndef SEC_E_NO_IP_ADDRESSES -#define SEC_E_NO_IP_ADDRESSES ((HRESULT)0x80090335L) -#endif -#ifndef SEC_E_WRONG_CREDENTIAL_HANDLE -#define SEC_E_WRONG_CREDENTIAL_HANDLE ((HRESULT)0x80090336L) -#endif -#ifndef SEC_E_CRYPTO_SYSTEM_INVALID -#define SEC_E_CRYPTO_SYSTEM_INVALID ((HRESULT)0x80090337L) -#endif -#ifndef SEC_E_MAX_REFERRALS_EXCEEDED -#define SEC_E_MAX_REFERRALS_EXCEEDED ((HRESULT)0x80090338L) -#endif -#ifndef SEC_E_MUST_BE_KDC -#define SEC_E_MUST_BE_KDC ((HRESULT)0x80090339L) -#endif -#ifndef SEC_E_STRONG_CRYPTO_NOT_SUPPORTED -#define SEC_E_STRONG_CRYPTO_NOT_SUPPORTED ((HRESULT)0x8009033AL) -#endif -#ifndef SEC_E_TOO_MANY_PRINCIPALS -#define SEC_E_TOO_MANY_PRINCIPALS ((HRESULT)0x8009033BL) -#endif -#ifndef SEC_E_NO_PA_DATA -#define SEC_E_NO_PA_DATA ((HRESULT)0x8009033CL) -#endif -#ifndef SEC_E_PKINIT_NAME_MISMATCH -#define SEC_E_PKINIT_NAME_MISMATCH ((HRESULT)0x8009033DL) -#endif -#ifndef SEC_E_SMARTCARD_LOGON_REQUIRED -#define SEC_E_SMARTCARD_LOGON_REQUIRED ((HRESULT)0x8009033EL) -#endif -#ifndef SEC_E_SHUTDOWN_IN_PROGRESS -#define SEC_E_SHUTDOWN_IN_PROGRESS ((HRESULT)0x8009033FL) -#endif -#ifndef SEC_E_KDC_INVALID_REQUEST -#define SEC_E_KDC_INVALID_REQUEST ((HRESULT)0x80090340L) -#endif -#ifndef SEC_E_KDC_UNABLE_TO_REFER -#define SEC_E_KDC_UNABLE_TO_REFER ((HRESULT)0x80090341L) -#endif -#ifndef SEC_E_KDC_UNKNOWN_ETYPE -#define SEC_E_KDC_UNKNOWN_ETYPE ((HRESULT)0x80090342L) -#endif -#ifndef SEC_E_UNSUPPORTED_PREAUTH -#define SEC_E_UNSUPPORTED_PREAUTH ((HRESULT)0x80090343L) -#endif -#ifndef SEC_E_DELEGATION_REQUIRED -#define SEC_E_DELEGATION_REQUIRED ((HRESULT)0x80090345L) -#endif -#ifndef SEC_E_BAD_BINDINGS -#define SEC_E_BAD_BINDINGS ((HRESULT)0x80090346L) -#endif -#ifndef SEC_E_MULTIPLE_ACCOUNTS -#define SEC_E_MULTIPLE_ACCOUNTS ((HRESULT)0x80090347L) -#endif -#ifndef SEC_E_NO_KERB_KEY -#define SEC_E_NO_KERB_KEY ((HRESULT)0x80090348L) -#endif -#ifndef SEC_E_CERT_WRONG_USAGE -#define SEC_E_CERT_WRONG_USAGE ((HRESULT)0x80090349L) -#endif -#ifndef SEC_E_DOWNGRADE_DETECTED -#define SEC_E_DOWNGRADE_DETECTED ((HRESULT)0x80090350L) -#endif -#ifndef SEC_E_SMARTCARD_CERT_REVOKED -#define SEC_E_SMARTCARD_CERT_REVOKED ((HRESULT)0x80090351L) -#endif -#ifndef SEC_E_ISSUING_CA_UNTRUSTED -#define SEC_E_ISSUING_CA_UNTRUSTED ((HRESULT)0x80090352L) -#endif -#ifndef SEC_E_REVOCATION_OFFLINE_C -#define SEC_E_REVOCATION_OFFLINE_C ((HRESULT)0x80090353L) -#endif -#ifndef SEC_E_PKINIT_CLIENT_FAILURE -#define SEC_E_PKINIT_CLIENT_FAILURE ((HRESULT)0x80090354L) -#endif -#ifndef SEC_E_SMARTCARD_CERT_EXPIRED -#define SEC_E_SMARTCARD_CERT_EXPIRED ((HRESULT)0x80090355L) -#endif -#ifndef SEC_E_NO_S4U_PROT_SUPPORT -#define SEC_E_NO_S4U_PROT_SUPPORT ((HRESULT)0x80090356L) -#endif -#ifndef SEC_E_CROSSREALM_DELEGATION_FAILURE -#define SEC_E_CROSSREALM_DELEGATION_FAILURE ((HRESULT)0x80090357L) -#endif -#ifndef SEC_E_REVOCATION_OFFLINE_KDC -#define SEC_E_REVOCATION_OFFLINE_KDC ((HRESULT)0x80090358L) -#endif -#ifndef SEC_E_ISSUING_CA_UNTRUSTED_KDC -#define SEC_E_ISSUING_CA_UNTRUSTED_KDC ((HRESULT)0x80090359L) -#endif -#ifndef SEC_E_KDC_CERT_EXPIRED -#define SEC_E_KDC_CERT_EXPIRED ((HRESULT)0x8009035AL) -#endif -#ifndef SEC_E_KDC_CERT_REVOKED -#define SEC_E_KDC_CERT_REVOKED ((HRESULT)0x8009035BL) -#endif -#endif /* __MINGW32CE__ */ /* Offered by mingw-w64 v8+. MS SDK 6.0A+. */ #ifndef SEC_E_INVALID_PARAMETER #define SEC_E_INVALID_PARAMETER ((HRESULT)0x8009035DL) @@ -302,44 +81,11 @@ extern PSecurityFunctionTable Curl_pSecFn; #define SEC_E_POLICY_NLTM_ONLY ((HRESULT)0x8009035FL) #endif -#ifdef __MINGW32CE__ -#ifndef SEC_I_CONTINUE_NEEDED -#define SEC_I_CONTINUE_NEEDED ((HRESULT)0x00090312L) -#endif -#ifndef SEC_I_COMPLETE_NEEDED -#define SEC_I_COMPLETE_NEEDED ((HRESULT)0x00090313L) -#endif -#ifndef SEC_I_COMPLETE_AND_CONTINUE -#define SEC_I_COMPLETE_AND_CONTINUE ((HRESULT)0x00090314L) -#endif -#ifndef SEC_I_LOCAL_LOGON -#define SEC_I_LOCAL_LOGON ((HRESULT)0x00090315L) -#endif -#ifndef SEC_I_CONTEXT_EXPIRED -#define SEC_I_CONTEXT_EXPIRED ((HRESULT)0x00090317L) -#endif -#ifndef SEC_I_INCOMPLETE_CREDENTIALS -#define SEC_I_INCOMPLETE_CREDENTIALS ((HRESULT)0x00090320L) -#endif -#ifndef SEC_I_RENEGOTIATE -#define SEC_I_RENEGOTIATE ((HRESULT)0x00090321L) -#endif -#ifndef SEC_I_NO_LSA_CONTEXT -#define SEC_I_NO_LSA_CONTEXT ((HRESULT)0x00090323L) -#endif -#endif /* __MINGW32CE__ */ - /* Offered by mingw-w64 v8+. MS SDK 6.0A+. */ #ifndef SEC_I_SIGNATURE_NEEDED #define SEC_I_SIGNATURE_NEEDED ((HRESULT)0x0009035CL) #endif -#ifdef __MINGW32CE__ -#ifndef CRYPT_E_NOT_IN_REVOCATION_DATABASE -#define CRYPT_E_NOT_IN_REVOCATION_DATABASE ((HRESULT)0x80092014L) -#endif -#endif /* __MINGW32CE__ */ - /* * Definitions required from ntsecapi.h are directly provided below this point * to avoid including ntsecapi.h due to a conflict with OpenSSL's safestack.h diff --git a/lib/curl_threads.c b/lib/curl_threads.c index 68bfddddcbcd..9e4bbc96eca2 100644 --- a/lib/curl_threads.c +++ b/lib/curl_threads.c @@ -24,16 +24,11 @@ #include "curl_setup.h" -#include - #if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) #include #endif #include "curl_threads.h" -#include "curl_memory.h" -/* The last #include FILE should be: */ -#include "memdebug.h" #ifdef USE_THREADS_POSIX @@ -48,7 +43,7 @@ static void *curl_thread_create_thunk(void *arg) unsigned int (*func)(void *) = ac->func; void *real_arg = ac->arg; - free(ac); + curlx_free(ac); (*func)(real_arg); @@ -58,8 +53,8 @@ static void *curl_thread_create_thunk(void *arg) curl_thread_t Curl_thread_create(CURL_THREAD_RETURN_T (CURL_STDCALL *func) (void *), void *arg) { - curl_thread_t t = malloc(sizeof(pthread_t)); - struct Curl_actual_call *ac = malloc(sizeof(struct Curl_actual_call)); + curl_thread_t t = curlx_malloc(sizeof(pthread_t)); + struct Curl_actual_call *ac = curlx_malloc(sizeof(struct Curl_actual_call)); int rc; if(!(ac && t)) goto err; @@ -69,15 +64,15 @@ curl_thread_t Curl_thread_create(CURL_THREAD_RETURN_T rc = pthread_create(t, NULL, curl_thread_create_thunk, ac); if(rc) { - CURL_SETERRNO(rc); + errno = rc; goto err; } return t; err: - free(t); - free(ac); + curlx_free(t); + curlx_free(ac); return curl_thread_t_null; } @@ -85,7 +80,7 @@ void Curl_thread_destroy(curl_thread_t *hnd) { if(*hnd != curl_thread_t_null) { pthread_detach(**hnd); - free(*hnd); + curlx_free(*hnd); *hnd = curl_thread_t_null; } } @@ -94,7 +89,7 @@ int Curl_thread_join(curl_thread_t *hnd) { int ret = (pthread_join(**hnd, NULL) == 0); - free(*hnd); + curlx_free(*hnd); *hnd = curl_thread_t_null; return ret; @@ -109,10 +104,9 @@ curl_thread_t Curl_thread_create(CURL_THREAD_RETURN_T if(!t) { DWORD gle = GetLastError(); /* !checksrc! disable ERRNOVAR 1 */ - int err = (gle == ERROR_ACCESS_DENIED || - gle == ERROR_NOT_ENOUGH_MEMORY) ? - EACCES : EINVAL; - CURL_SETERRNO(err); + errno = (gle == ERROR_ACCESS_DENIED || + gle == ERROR_NOT_ENOUGH_MEMORY) ? + EACCES : EINVAL; return curl_thread_t_null; } return t; @@ -128,11 +122,7 @@ void Curl_thread_destroy(curl_thread_t *hnd) int Curl_thread_join(curl_thread_t *hnd) { -#ifdef UNDER_CE - int ret = (WaitForSingleObject(*hnd, INFINITE) == WAIT_OBJECT_0); -#else int ret = (WaitForSingleObjectEx(*hnd, INFINITE, FALSE) == WAIT_OBJECT_0); -#endif Curl_thread_destroy(hnd); diff --git a/lib/curl_trc.c b/lib/curl_trc.c index 0b91315e3668..fd80a76ee5a7 100644 --- a/lib/curl_trc.c +++ b/lib/curl_trc.c @@ -24,17 +24,13 @@ #include "curl_setup.h" -#include - #include "curl_trc.h" #include "urldata.h" -#include "easyif.h" #include "cfilters.h" #include "multiif.h" #include "cf-socket.h" #include "connect.h" -#include "doh.h" #include "http2.h" #include "http_proxy.h" #include "cf-h1-proxy.h" @@ -42,14 +38,12 @@ #include "cf-haproxy.h" #include "cf-https-connect.h" #include "cf-ip-happy.h" +#include "progress.h" #include "socks.h" #include "curlx/strparse.h" #include "vtls/vtls.h" #include "vquic/vquic.h" - -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" +#include "curlx/strcopy.h" static void trc_write(struct Curl_easy *data, curl_infotype type, const char *ptr, size_t size) @@ -191,7 +185,7 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...) len = curl_mvsnprintf(error, CURL_ERROR_SIZE, fmt, ap); if(data->set.errorbuffer && !data->state.errorbuf) { - strcpy(data->set.errorbuffer, error); + curlx_strcopy(data->set.errorbuffer, CURL_ERROR_SIZE, error, len); data->state.errorbuf = TRUE; /* wrote error string */ } error[len++] = '\n'; @@ -276,7 +270,7 @@ struct curl_trc_feat Curl_trc_feat_timer = { CURL_LOG_LVL_NONE, }; -static const char * const Curl_trc_timer_names[]={ +static const char * const Curl_trc_timer_names[] = { "100_TIMEOUT", "ASYNC_NAME", "CONNECTTIMEOUT", @@ -318,25 +312,24 @@ void Curl_trc_easy_timers(struct Curl_easy *data) if(CURL_TRC_TIMER_is_verbose(data)) { struct Curl_llist_node *e = Curl_llist_head(&data->state.timeoutlist); if(e) { - struct curltime now = curlx_now(); + const struct curltime *pnow = Curl_pgrs_now(data); while(e) { struct time_node *n = Curl_node_elem(e); e = Curl_node_next(e); CURL_TRC_TIMER(data, n->eid, "expires in %" FMT_TIMEDIFF_T "ns", - curlx_timediff_us(n->time, now)); + curlx_ptimediff_us(&n->time, pnow)); } } } } -static const char * const Curl_trc_mstate_names[]={ +static const char * const Curl_trc_mstate_names[] = { "INIT", "PENDING", "SETUP", "CONNECT", "RESOLVING", "CONNECTING", - "TUNNELING", "PROTOCONNECT", "PROTOCONNECTING", "DO", @@ -457,6 +450,24 @@ void Curl_trc_ssls(struct Curl_easy *data, const char *fmt, ...) } #endif /* USE_SSL */ +#ifdef USE_SSH +struct curl_trc_feat Curl_trc_feat_ssh = { + "SSH", + CURL_LOG_LVL_NONE, +}; + +void Curl_trc_ssh(struct Curl_easy *data, const char *fmt, ...) +{ + DEBUGASSERT(!strchr(fmt, '\n')); + if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ssh)) { + va_list ap; + va_start(ap, fmt); + trc_infof(data, &Curl_trc_feat_ssh, NULL, 0, fmt, ap); + va_end(ap); + } +} +#endif /* USE_SSH */ + #if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP) struct curl_trc_feat Curl_trc_feat_ws = { "WS", @@ -476,10 +487,10 @@ void Curl_trc_ws(struct Curl_easy *data, const char *fmt, ...) #endif /* !CURL_DISABLE_WEBSOCKETS && !CURL_DISABLE_HTTP */ #define TRC_CT_NONE (0) -#define TRC_CT_PROTOCOL (1<<(0)) -#define TRC_CT_NETWORK (1<<(1)) -#define TRC_CT_PROXY (1<<(2)) -#define TRC_CT_INTERNALS (1<<(3)) +#define TRC_CT_PROTOCOL (1 << 0) +#define TRC_CT_NETWORK (1 << 1) +#define TRC_CT_PROXY (1 << 2) +#define TRC_CT_INTERNALS (1 << 3) struct trc_feat_def { struct curl_trc_feat *feat; @@ -496,14 +507,15 @@ static struct trc_feat_def trc_feats[] = { #ifndef CURL_DISABLE_FTP { &Curl_trc_feat_ftp, TRC_CT_PROTOCOL }, #endif -#ifndef CURL_DISABLE_DOH -#endif #ifndef CURL_DISABLE_SMTP { &Curl_trc_feat_smtp, TRC_CT_PROTOCOL }, #endif #ifdef USE_SSL { &Curl_trc_feat_ssls, TRC_CT_NETWORK }, #endif +#ifdef USE_SSH + { &Curl_trc_feat_ssh, TRC_CT_PROTOCOL }, +#endif #if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP) { &Curl_trc_feat_ws, TRC_CT_PROTOCOL }, #endif @@ -648,56 +660,75 @@ CURLcode Curl_trc_init(void) void Curl_infof(struct Curl_easy *data, const char *fmt, ...) { - (void)data; (void)fmt; + (void)data; + (void)fmt; } void Curl_trc_cf_infof(struct Curl_easy *data, const struct Curl_cfilter *cf, const char *fmt, ...) { - (void)data; (void)cf; (void)fmt; + (void)data; + (void)cf; + (void)fmt; } void Curl_trc_multi(struct Curl_easy *data, const char *fmt, ...) { - (void)data; (void)fmt; + (void)data; + (void)fmt; } void Curl_trc_write(struct Curl_easy *data, const char *fmt, ...) { - (void)data; (void)fmt; + (void)data; + (void)fmt; } void Curl_trc_dns(struct Curl_easy *data, const char *fmt, ...) { - (void)data; (void)fmt; + (void)data; + (void)fmt; } void Curl_trc_timer(struct Curl_easy *data, int tid, const char *fmt, ...) { - (void)data; (void)tid; (void)fmt; + (void)data; + (void)tid; + (void)fmt; } void Curl_trc_read(struct Curl_easy *data, const char *fmt, ...) { - (void)data; (void)fmt; + (void)data; + (void)fmt; } #ifndef CURL_DISABLE_FTP void Curl_trc_ftp(struct Curl_easy *data, const char *fmt, ...) { - (void)data; (void)fmt; + (void)data; + (void)fmt; } #endif #ifndef CURL_DISABLE_SMTP void Curl_trc_smtp(struct Curl_easy *data, const char *fmt, ...) { - (void)data; (void)fmt; + (void)data; + (void)fmt; } #endif #if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP) void Curl_trc_ws(struct Curl_easy *data, const char *fmt, ...) { - (void)data; (void)fmt; + (void)data; + (void)fmt; +} +#endif +#ifdef USE_SSH +void Curl_trc_ssh(struct Curl_easy *data, const char *fmt, ...) +{ + (void)data; + (void)fmt; } #endif #ifdef USE_SSL diff --git a/lib/curl_trc.h b/lib/curl_trc.h index 1a3f8f374e2d..6d6a22ef9909 100644 --- a/lib/curl_trc.h +++ b/lib/curl_trc.h @@ -65,7 +65,6 @@ void Curl_failf(struct Curl_easy *data, #define CURL_LOG_LVL_NONE 0 #define CURL_LOG_LVL_INFO 1 - #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define CURL_HAVE_C99 #endif @@ -117,6 +116,11 @@ extern struct curl_trc_feat Curl_trc_feat_ssls; void Curl_trc_ssls(struct Curl_easy *data, const char *fmt, ...) CURL_PRINTF(2, 3); #endif +#ifdef USE_SSH +extern struct curl_trc_feat Curl_trc_feat_ssh; +void Curl_trc_ssh(struct Curl_easy *data, + const char *fmt, ...) CURL_PRINTF(2, 3); +#endif #if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP) extern struct curl_trc_feat Curl_trc_feat_ws; void Curl_trc_ws(struct Curl_easy *data, @@ -168,6 +172,11 @@ void Curl_trc_ws(struct Curl_easy *data, do { if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ssls)) \ Curl_trc_ssls(data, __VA_ARGS__); } while(0) #endif /* USE_SSL */ +#ifdef USE_SSH +#define CURL_TRC_SSH(data, ...) \ + do { if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ssh)) \ + Curl_trc_ssh(data, __VA_ARGS__); } while(0) +#endif /* USE_SSH */ #if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP) #define CURL_TRC_WS(data, ...) \ do { if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_ws)) \ @@ -176,9 +185,9 @@ void Curl_trc_ws(struct Curl_easy *data, #else /* CURL_HAVE_C99 */ -#define infof Curl_infof -#define CURL_TRC_M Curl_trc_multi -#define CURL_TRC_CF Curl_trc_cf_infof +#define infof Curl_infof +#define CURL_TRC_M Curl_trc_multi +#define CURL_TRC_CF Curl_trc_cf_infof #define CURL_TRC_WRITE Curl_trc_write #define CURL_TRC_READ Curl_trc_read #define CURL_TRC_DNS Curl_trc_dns @@ -193,6 +202,9 @@ void Curl_trc_ws(struct Curl_easy *data, #ifdef USE_SSL #define CURL_TRC_SSLS Curl_trc_ssls #endif +#ifdef USE_SSH +#define CURL_TRC_SSH Curl_trc_ssh +#endif #if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP) #define CURL_TRC_WS Curl_trc_ws #endif @@ -227,8 +239,8 @@ extern struct curl_trc_feat Curl_trc_feat_timer; /* All informational messages are not compiled in for size savings */ #define Curl_trc_is_verbose(d) (FALSE) -#define Curl_trc_cf_is_verbose(x,y) (FALSE) -#define Curl_trc_ft_is_verbose(x,y) (FALSE) +#define Curl_trc_cf_is_verbose(x, y) (FALSE) +#define Curl_trc_ft_is_verbose(x, y) (FALSE) #define CURL_MSTATE_NAME(x) ((void)(x), "-") #define CURL_TRC_EASY_TIMERS(x) Curl_nop_stmt diff --git a/lib/curlx/base64.c b/lib/curlx/base64.c index 5f6887bd5c4c..0e44eae7faf3 100644 --- a/lib/curlx/base64.c +++ b/lib/curlx/base64.c @@ -26,31 +26,24 @@ #include "../curl_setup.h" -#include -#include "warnless.h" #include "base64.h" -/* The last 2 #include files should be in this order */ -#ifdef BUILDING_LIBCURL -#include "../curl_memory.h" -#endif -#include "../memdebug.h" - /* ---- Base64 Encoding/Decoding Table --- */ -const char Curl_base64encdec[]= +const char curlx_base64encdec[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /* The Base 64 encoding with a URL and filename safe alphabet, RFC 4648 section 5 */ -static const char base64url[]= +static const char base64url[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; -static const unsigned char decodetable[] = -{ 62, 255, 255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255, - 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, 255, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51 }; +static const unsigned char decodetable[] = { + 62, 255, 255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, + 255, 255, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 255, 255, 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 +}; /* * curlx_base64_decode() * @@ -66,7 +59,7 @@ static const unsigned char decodetable[] = * @unittest: 1302 */ CURLcode curlx_base64_decode(const char *src, - unsigned char **outptr, size_t *outlen) + uint8_t **outptr, size_t *outlen) { size_t srclen = 0; size_t padding = 0; @@ -103,7 +96,7 @@ CURLcode curlx_base64_decode(const char *src, rawlen = (numQuantums * 3) - padding; /* Allocate our buffer including room for a null-terminator */ - newstr = malloc(rawlen + 1); + newstr = curlx_malloc(rawlen + 1); if(!newstr) return CURLE_OUT_OF_MEMORY; @@ -165,13 +158,13 @@ CURLcode curlx_base64_decode(const char *src, return CURLE_OK; bad: - free(newstr); + curlx_free(newstr); return CURLE_BAD_CONTENT_ENCODING; } static CURLcode base64_encode(const char *table64, - unsigned char padbyte, - const char *inputbuff, size_t insize, + uint8_t padbyte, + const uint8_t *inputbuff, size_t insize, char **outptr, size_t *outlen) { char *output; @@ -184,28 +177,28 @@ static CURLcode base64_encode(const char *table64, if(!insize) return CURLE_OK; -#if SIZEOF_SIZE_T == 4 - if(insize > UINT_MAX/4) - return CURLE_OUT_OF_MEMORY; -#endif + /* safety precaution */ + DEBUGASSERT(insize <= CURL_MAX_BASE64_INPUT); + if(insize > CURL_MAX_BASE64_INPUT) + return CURLE_TOO_LARGE; - base64data = output = malloc((insize + 2) / 3 * 4 + 1); + base64data = output = curlx_malloc((insize + 2) / 3 * 4 + 1); if(!output) return CURLE_OUT_OF_MEMORY; while(insize >= 3) { - *output++ = table64[ in[0] >> 2 ]; - *output++ = table64[ ((in[0] & 0x03) << 4) | (in[1] >> 4) ]; - *output++ = table64[ ((in[1] & 0x0F) << 2) | ((in[2] & 0xC0) >> 6) ]; - *output++ = table64[ in[2] & 0x3F ]; + *output++ = table64[in[0] >> 2]; + *output++ = table64[((in[0] & 0x03) << 4) | (in[1] >> 4)]; + *output++ = table64[((in[1] & 0x0F) << 2) | ((in[2] & 0xC0) >> 6)]; + *output++ = table64[in[2] & 0x3F]; insize -= 3; in += 3; } if(insize) { /* this is only one or two bytes now */ - *output++ = table64[ in[0] >> 2 ]; + *output++ = table64[in[0] >> 2]; if(insize == 1) { - *output++ = table64[ ((in[0] & 0x03) << 4) ]; + *output++ = table64[((in[0] & 0x03) << 4)]; if(padbyte) { *output++ = padbyte; *output++ = padbyte; @@ -213,8 +206,8 @@ static CURLcode base64_encode(const char *table64, } else { /* insize == 2 */ - *output++ = table64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xF0) >> 4) ]; - *output++ = table64[ ((in[1] & 0x0F) << 2) ]; + *output++ = table64[((in[0] & 0x03) << 4) | ((in[1] & 0xF0) >> 4)]; + *output++ = table64[((in[1] & 0x0F) << 2)]; if(padbyte) *output++ = padbyte; } @@ -245,10 +238,10 @@ static CURLcode base64_encode(const char *table64, * * @unittest: 1302 */ -CURLcode curlx_base64_encode(const char *inputbuff, size_t insize, +CURLcode curlx_base64_encode(const uint8_t *inputbuff, size_t insize, char **outptr, size_t *outlen) { - return base64_encode(Curl_base64encdec, '=', + return base64_encode(curlx_base64encdec, '=', inputbuff, insize, outptr, outlen); } @@ -267,7 +260,7 @@ CURLcode curlx_base64_encode(const char *inputbuff, size_t insize, * * @unittest: 1302 */ -CURLcode curlx_base64url_encode(const char *inputbuff, size_t insize, +CURLcode curlx_base64url_encode(const uint8_t *inputbuff, size_t insize, char **outptr, size_t *outlen) { return base64_encode(base64url, 0, inputbuff, insize, outptr, outlen); diff --git a/lib/curlx/base64.h b/lib/curlx/base64.h index 026f80e4d37f..2e7781482237 100644 --- a/lib/curlx/base64.h +++ b/lib/curlx/base64.h @@ -24,13 +24,17 @@ * ***************************************************************************/ -CURLcode curlx_base64_encode(const char *inputbuff, size_t insize, +CURLcode curlx_base64_encode(const uint8_t *inputbuff, size_t insize, char **outptr, size_t *outlen); -CURLcode curlx_base64url_encode(const char *inputbuff, size_t insize, +CURLcode curlx_base64url_encode(const uint8_t *inputbuff, size_t insize, char **outptr, size_t *outlen); CURLcode curlx_base64_decode(const char *src, - unsigned char **outptr, size_t *outlen); + uint8_t **outptr, size_t *outlen); -extern const char Curl_base64encdec[]; +extern const char curlx_base64encdec[]; + +/* maximum input length acceptable to base64 encode, here to catch and prevent + mistakes */ +#define CURL_MAX_BASE64_INPUT 16000000 #endif /* HEADER_CURL_BASE64_H */ diff --git a/lib/curlx/binmode.h b/lib/curlx/binmode.h index 3f356edd597c..991cc89045e2 100644 --- a/lib/curlx/binmode.h +++ b/lib/curlx/binmode.h @@ -33,7 +33,7 @@ # define CURLX_SET_BINMODE(stream) (void)setmode(fileno(stream), O_BINARY) #endif #else -# define CURLX_SET_BINMODE(stream) (void)stream; Curl_nop_stmt +# define CURLX_SET_BINMODE(stream) (void)stream #endif #endif /* HEADER_CURL_TOOL_BINMODE_H */ diff --git a/lib/curlx/curlx.h b/lib/curlx/curlx.h index 480e91950de0..817acb07cde9 100644 --- a/lib/curlx/curlx.h +++ b/lib/curlx/curlx.h @@ -37,14 +37,6 @@ #include "nonblock.h" /* "nonblock.h" provides curlx_nonblock() */ -#include "warnless.h" -/* "warnless.h" provides functions: - - curlx_ultous() - curlx_ultouc() - curlx_uztosi() -*/ - #include "multibyte.h" /* "multibyte.h" provides these functions and macros: @@ -52,7 +44,6 @@ curlx_convert_wchar_to_UTF8() curlx_convert_UTF8_to_tchar() curlx_convert_tchar_to_UTF8() - curlx_unicodefree() */ #include "version_win32.h" @@ -64,6 +55,9 @@ #include "strparse.h" /* The curlx_str_* parsing functions */ +#include "strcopy.h" +/* curlx_strcopy */ + #include "dynbuf.h" /* The curlx_dyn_* functions */ diff --git a/lib/curlx/dynbuf.c b/lib/curlx/dynbuf.c index 447203e42a8a..a9ff48367f62 100644 --- a/lib/curlx/dynbuf.c +++ b/lib/curlx/dynbuf.c @@ -25,10 +25,6 @@ #include "../curl_setup.h" #include "dynbuf.h" #include "../curl_printf.h" -#ifdef BUILDING_LIBCURL -#include "../curl_memory.h" -#endif -#include "../memdebug.h" #define MIN_FIRST_ALLOC 32 @@ -108,7 +104,7 @@ static CURLcode dyn_nappend(struct dynbuf *s, if(a != s->allc) { /* this logic is not using Curl_saferealloc() to make the tool not have to include that as well when it uses this code */ - void *p = realloc(s->bufr, a); + void *p = curlx_realloc(s->bufr, a); if(!p) { curlx_dyn_free(s); return CURLE_OUT_OF_MEMORY; @@ -160,7 +156,6 @@ CURLcode curlx_dyn_tail(struct dynbuf *s, size_t trail) s->bufr[s->leng] = 0; } return CURLE_OK; - } /* @@ -212,7 +207,7 @@ CURLcode curlx_dyn_vaddf(struct dynbuf *s, const char *fmt, va_list ap) if(str) { CURLcode result = dyn_nappend(s, (const unsigned char *)str, strlen(str)); - free(str); + curlx_free(str); return result; } /* If we failed, we cleanup the whole buffer and return error */ diff --git a/lib/curlx/dynbuf.h b/lib/curlx/dynbuf.h index 00ca04789360..6f09e1322eae 100644 --- a/lib/curlx/dynbuf.h +++ b/lib/curlx/dynbuf.h @@ -24,15 +24,13 @@ * ***************************************************************************/ -#include - struct dynbuf { char *bufr; /* point to a null-terminated allocated buffer */ size_t leng; /* number of bytes *EXCLUDING* the null-terminator */ size_t allc; /* size of the current allocation */ size_t toobig; /* size limit for the buffer */ #ifdef DEBUGBUILD - int init; /* detect API usage mistakes */ + int init; /* detect API usage mistakes */ #endif }; @@ -62,24 +60,24 @@ int curlx_dyn_vprintf(struct dynbuf *dyn, const char *format, va_list ap_save); char *curlx_dyn_take(struct dynbuf *s, size_t *plen); /* Dynamic buffer max sizes */ -#define MAX_DYNBUF_SIZE (SIZE_MAX/2) +#define MAX_DYNBUF_SIZE (SIZE_MAX / 2) #define DYN_DOH_RESPONSE 3000 #define DYN_DOH_CNAME 256 #define DYN_PAUSE_BUFFER (64 * 1024 * 1024) #define DYN_HAXPROXY 2048 -#define DYN_HTTP_REQUEST (1024*1024) +#define DYN_HTTP_REQUEST (1024 * 1024) #define DYN_APRINTF 8000000 -#define DYN_RTSP_REQ_HEADER (64*1024) -#define DYN_TRAILERS (64*1024) +#define DYN_RTSP_REQ_HEADER (64 * 1024) +#define DYN_TRAILERS (64 * 1024) #define DYN_PROXY_CONNECT_HEADERS 16384 #define DYN_QLOG_NAME 1024 #define DYN_H1_TRAILER 4096 -#define DYN_PINGPPONG_CMD (64*1024) -#define DYN_IMAP_CMD (64*1024) -#define DYN_MQTT_RECV (64*1024) +#define DYN_PINGPPONG_CMD (64 * 1024) +#define DYN_IMAP_CMD (64 * 1024) +#define DYN_MQTT_RECV (64 * 1024) #define DYN_MQTT_SEND 0xFFFFFFF -#define DYN_CRLFILE_SIZE (400*1024*1024) /* 400mb */ -#define DYN_CERTFILE_SIZE (100*1024) /* 100KiB */ -#define DYN_KEYFILE_SIZE (100*1024) /* 100KiB */ +#define DYN_CRLFILE_SIZE (400 * 1024 * 1024) /* 400MiB */ +#define DYN_CERTFILE_SIZE (100 * 1024) /* 100KiB */ +#define DYN_KEYFILE_SIZE (100 * 1024) /* 100KiB */ #endif diff --git a/lib/curlx/fopen.c b/lib/curlx/fopen.c index 22c7259c70dd..ac2552a1c35e 100644 --- a/lib/curlx/fopen.c +++ b/lib/curlx/fopen.c @@ -22,20 +22,64 @@ * ***************************************************************************/ -/* - * This file is 'mem-include-scan' clean, which means its memory allocations - * are not tracked by the curl memory tracker memdebug, so they must not use - * `CURLDEBUG` macro replacements in memdebug.h for free, malloc, etc. To avoid - * these macro replacements, wrap the names in parentheses to call the original - * versions: `ptr = (malloc)(123)`, `(free)(ptr)`, etc. - */ - #include "../curl_setup.h" -#if defined(_WIN32) && !defined(UNDER_CE) - #include "fopen.h" + +int curlx_fseek(void *stream, curl_off_t offset, int whence) +{ +#ifdef _WIN32 + return _fseeki64(stream, (__int64)offset, whence); +#elif defined(HAVE_FSEEKO) && defined(HAVE_DECL_FSEEKO) + return fseeko(stream, (off_t)offset, whence); +#else + if(offset > LONG_MAX) + return -1; + return fseek(stream, (long)offset, whence); +#endif +} + +#ifdef _WIN32 + +#include /* for _SH_DENYNO */ + #include "multibyte.h" +#include "timeval.h" + +#ifdef CURLDEBUG +/* + * Use system allocators to avoid infinite recursion when called by curl's + * memory tracker memdebug functions. + */ +#define CURLX_MALLOC(x) malloc(x) +#define CURLX_FREE(x) free(x) +#else +#define CURLX_MALLOC(x) curlx_malloc(x) +#define CURLX_FREE(x) curlx_free(x) +#endif + +#ifdef _UNICODE +static wchar_t *fn_convert_UTF8_to_wchar(const char *str_utf8) +{ + wchar_t *str_w = NULL; + + if(str_utf8) { + int str_w_len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, + str_utf8, -1, NULL, 0); + if(str_w_len > 0) { + str_w = CURLX_MALLOC(str_w_len * sizeof(wchar_t)); + if(str_w) { + if(MultiByteToWideChar(CP_UTF8, 0, + str_utf8, -1, str_w, str_w_len) == 0) { + CURLX_FREE(str_w); + return NULL; + } + } + } + } + return str_w; +} +#endif /* declare GetFullPathNameW for mingw-w64 UWP builds targeting old windows */ #if defined(CURL_WINDOWS_UWP) && defined(__MINGW32__) && \ @@ -83,15 +127,16 @@ static bool fix_excessive_path(const TCHAR *in, TCHAR **out) #ifndef _UNICODE /* convert multibyte input to unicode */ - needed = mbstowcs(NULL, in, 0); - if(needed == (size_t)-1 || needed >= max_path_len) + if(mbstowcs_s(&needed, NULL, 0, in, 0)) goto cleanup; - ++needed; /* for NUL */ - ibuf = (malloc)(needed * sizeof(wchar_t)); + if(!needed || needed >= max_path_len) + goto cleanup; + ibuf = CURLX_MALLOC(needed * sizeof(wchar_t)); if(!ibuf) goto cleanup; - count = mbstowcs(ibuf, in, needed); - if(count == (size_t)-1 || count >= needed) + if(mbstowcs_s(&count, ibuf, needed, in, needed - 1)) + goto cleanup; + if(count != needed) goto cleanup; in_w = ibuf; #else @@ -107,7 +152,7 @@ static bool fix_excessive_path(const TCHAR *in, TCHAR **out) /* skip paths that are not excessive and do not need modification */ if(needed <= MAX_PATH) goto cleanup; - fbuf = (malloc)(needed * sizeof(wchar_t)); + fbuf = CURLX_MALLOC(needed * sizeof(wchar_t)); if(!fbuf) goto cleanup; count = (size_t)GetFullPathNameW(in_w, (DWORD)needed, fbuf, NULL); @@ -128,7 +173,7 @@ static bool fix_excessive_path(const TCHAR *in, TCHAR **out) else if(!wcsncmp(fbuf, L"\\\\.\\", 4)) fbuf[2] = '?'; else if(!wcsncmp(fbuf, L"\\\\.", 3) || !wcsncmp(fbuf, L"\\\\?", 3)) { - /* Unexpected, not UNC. The formatting doc doesn't allow this AFAICT. */ + /* Unexpected, not UNC. The formatting doc does not allow this AFAICT. */ goto cleanup; } else { @@ -140,12 +185,18 @@ static bool fix_excessive_path(const TCHAR *in, TCHAR **out) if(needed > max_path_len) goto cleanup; - temp = (malloc)(needed * sizeof(wchar_t)); + temp = CURLX_MALLOC(needed * sizeof(wchar_t)); if(!temp) goto cleanup; - wcsncpy(temp, L"\\\\?\\UNC\\", 8); - wcscpy(temp + 8, fbuf + 2); + if(wcsncpy_s(temp, needed, L"\\\\?\\UNC\\", 8)) { + CURLX_FREE(temp); + goto cleanup; + } + if(wcscpy_s(temp + 8, needed, fbuf + 2)) { + CURLX_FREE(temp); + goto cleanup; + } } else { /* "\\?\" + full path + null */ @@ -153,29 +204,36 @@ static bool fix_excessive_path(const TCHAR *in, TCHAR **out) if(needed > max_path_len) goto cleanup; - temp = (malloc)(needed * sizeof(wchar_t)); + temp = CURLX_MALLOC(needed * sizeof(wchar_t)); if(!temp) goto cleanup; - wcsncpy(temp, L"\\\\?\\", 4); - wcscpy(temp + 4, fbuf); + if(wcsncpy_s(temp, needed, L"\\\\?\\", 4)) { + CURLX_FREE(temp); + goto cleanup; + } + if(wcscpy_s(temp + 4, needed, fbuf)) { + CURLX_FREE(temp); + goto cleanup; + } } - (free)(fbuf); + CURLX_FREE(fbuf); fbuf = temp; } #ifndef _UNICODE /* convert unicode full path to multibyte output */ - needed = wcstombs(NULL, fbuf, 0); - if(needed == (size_t)-1 || needed >= max_path_len) + if(wcstombs_s(&needed, NULL, 0, fbuf, 0)) goto cleanup; - ++needed; /* for NUL */ - obuf = (malloc)(needed); + if(!needed || needed >= max_path_len) + goto cleanup; + obuf = CURLX_MALLOC(needed); if(!obuf) goto cleanup; - count = wcstombs(obuf, fbuf, needed); - if(count == (size_t)-1 || count >= needed) + if(wcstombs_s(&count, obuf, needed, fbuf, needed - 1)) + goto cleanup; + if(count != needed) goto cleanup; *out = obuf; obuf = NULL; @@ -185,14 +243,57 @@ static bool fix_excessive_path(const TCHAR *in, TCHAR **out) #endif cleanup: - (free)(fbuf); + CURLX_FREE(fbuf); #ifndef _UNICODE - (free)(ibuf); - (free)(obuf); + CURLX_FREE(ibuf); + CURLX_FREE(obuf); #endif return *out ? true : false; } +#ifndef CURL_WINDOWS_UWP +HANDLE curlx_CreateFile(const char *filename, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile) +{ + HANDLE handle = INVALID_HANDLE_VALUE; + +#ifdef UNICODE + TCHAR *filename_t = curlx_convert_UTF8_to_wchar(filename); +#else + const TCHAR *filename_t = filename; +#endif + + if(filename_t) { + TCHAR *fixed = NULL; + const TCHAR *target = NULL; + + if(fix_excessive_path(filename_t, &fixed)) + target = fixed; + else + target = filename_t; + /* !checksrc! disable BANNEDFUNC 1 */ + handle = CreateFile(target, + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); + CURLX_FREE(fixed); +#ifdef UNICODE + curlx_free(filename_t); +#endif + } + + return handle; +} +#endif /* !CURL_WINDOWS_UWP */ + int curlx_win32_open(const char *filename, int oflag, ...) { int pmode = 0; @@ -201,7 +302,7 @@ int curlx_win32_open(const char *filename, int oflag, ...) const TCHAR *target = NULL; #ifdef _UNICODE - wchar_t *filename_w = curlx_convert_UTF8_to_wchar(filename); + wchar_t *filename_w = fn_convert_UTF8_to_wchar(filename); #endif va_list param; @@ -216,21 +317,21 @@ int curlx_win32_open(const char *filename, int oflag, ...) target = fixed; else target = filename_w; - result = _wopen(target, oflag, pmode); - curlx_unicodefree(filename_w); + errno = _wsopen_s(&result, target, oflag, _SH_DENYNO, pmode); + CURLX_FREE(filename_w); } else /* !checksrc! disable ERRNOVAR 1 */ - CURL_SETERRNO(EINVAL); + errno = EINVAL; #else if(fix_excessive_path(filename, &fixed)) target = fixed; else target = filename; - result = _open(target, oflag, pmode); + errno = _sopen_s(&result, target, oflag, _SH_DENYNO, pmode); #endif - (free)(fixed); + CURLX_FREE(fixed); return result; } @@ -241,30 +342,67 @@ FILE *curlx_win32_fopen(const char *filename, const char *mode) const TCHAR *target = NULL; #ifdef _UNICODE - wchar_t *filename_w = curlx_convert_UTF8_to_wchar(filename); - wchar_t *mode_w = curlx_convert_UTF8_to_wchar(mode); + wchar_t *filename_w = fn_convert_UTF8_to_wchar(filename); + wchar_t *mode_w = fn_convert_UTF8_to_wchar(mode); if(filename_w && mode_w) { if(fix_excessive_path(filename_w, &fixed)) target = fixed; else target = filename_w; - result = _wfopen(target, mode_w); + errno = _wfopen_s(&result, target, mode_w); } else /* !checksrc! disable ERRNOVAR 1 */ - CURL_SETERRNO(EINVAL); - curlx_unicodefree(filename_w); - curlx_unicodefree(mode_w); + errno = EINVAL; + CURLX_FREE(filename_w); + CURLX_FREE(mode_w); #else if(fix_excessive_path(filename, &fixed)) target = fixed; else target = filename; - /* !checksrc! disable BANNEDFUNC 1 */ - result = fopen(target, mode); + errno = fopen_s(&result, target, mode); #endif - (free)(fixed); + CURLX_FREE(fixed); + return result; +} + +#if defined(__MINGW32__) && (__MINGW64_VERSION_MAJOR < 5) +_CRTIMP errno_t __cdecl freopen_s(FILE **file, const char *filename, + const char *mode, FILE *stream); +#endif + +FILE *curlx_win32_freopen(const char *filename, const char *mode, FILE *fp) +{ + FILE *result = NULL; + TCHAR *fixed = NULL; + const TCHAR *target = NULL; + +#ifdef _UNICODE + wchar_t *filename_w = fn_convert_UTF8_to_wchar(filename); + wchar_t *mode_w = fn_convert_UTF8_to_wchar(mode); + if(filename_w && mode_w) { + if(fix_excessive_path(filename_w, &fixed)) + target = fixed; + else + target = filename_w; + errno = _wfreopen_s(&result, target, mode_w, fp); + } + else + /* !checksrc! disable ERRNOVAR 1 */ + errno = EINVAL; + CURLX_FREE(filename_w); + CURLX_FREE(mode_w); +#else + if(fix_excessive_path(filename, &fixed)) + target = fixed; + else + target = filename; + errno = freopen_s(&result, target, mode, fp); +#endif + + CURLX_FREE(fixed); return result; } @@ -281,30 +419,91 @@ int curlx_win32_stat(const char *path, struct_stat *buffer) target = fixed; else target = path_w; -#ifndef USE_WIN32_LARGE_FILES - result = _wstat(target, buffer); -#else result = _wstati64(target, buffer); -#endif - curlx_unicodefree(path_w); + curlx_free(path_w); } else /* !checksrc! disable ERRNOVAR 1 */ - CURL_SETERRNO(EINVAL); + errno = EINVAL; #else if(fix_excessive_path(path, &fixed)) target = fixed; else target = path; -#ifndef USE_WIN32_LARGE_FILES - result = _stat(target, buffer); -#else result = _stati64(target, buffer); -#endif #endif - (free)(fixed); + CURLX_FREE(fixed); return result; } -#endif /* _WIN32 && !UNDER_CE */ +#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_COOKIES) || \ + !defined(CURL_DISABLE_ALTSVC) +/* rename() on Windows does not overwrite, so we cannot use it here. + MoveFileEx() will overwrite and is usually atomic, however it fails + when there are open handles to the file. */ +int curlx_win32_rename(const char *oldpath, const char *newpath) +{ + int res = -1; /* fail */ + +#ifdef UNICODE + TCHAR *tchar_oldpath = curlx_convert_UTF8_to_wchar(oldpath); + TCHAR *tchar_newpath = curlx_convert_UTF8_to_wchar(newpath); +#else + const TCHAR *tchar_oldpath = oldpath; + const TCHAR *tchar_newpath = newpath; +#endif + + if(tchar_oldpath && tchar_newpath) { + const int max_wait_ms = 1000; + struct curltime start; + + TCHAR *oldpath_fixed = NULL; + TCHAR *newpath_fixed = NULL; + const TCHAR *target_oldpath; + const TCHAR *target_newpath; + + if(fix_excessive_path(tchar_oldpath, &oldpath_fixed)) + target_oldpath = oldpath_fixed; + else + target_oldpath = tchar_oldpath; + + if(fix_excessive_path(tchar_newpath, &newpath_fixed)) + target_newpath = newpath_fixed; + else + target_newpath = tchar_newpath; + + start = curlx_now(); + + for(;;) { + timediff_t diff; + /* !checksrc! disable BANNEDFUNC 1 */ + if(MoveFileEx(target_oldpath, target_newpath, + MOVEFILE_REPLACE_EXISTING)) { + res = 0; /* success */ + break; + } + diff = curlx_timediff_ms(curlx_now(), start); + if(diff < 0 || diff > max_wait_ms) { + break; + } + Sleep(1); + } + + CURLX_FREE(oldpath_fixed); + CURLX_FREE(newpath_fixed); + } + +#ifdef UNICODE + curlx_free(tchar_oldpath); + curlx_free(tchar_newpath); +#endif + + return res; +} +#endif + +#undef CURLX_MALLOC +#undef CURLX_FREE + +#endif /* _WIN32 */ diff --git a/lib/curlx/fopen.h b/lib/curlx/fopen.h index b44cbbdfced2..4cda50df1c46 100644 --- a/lib/curlx/fopen.h +++ b/lib/curlx/fopen.h @@ -32,25 +32,46 @@ #include /* for open() and attributes */ #endif -#if defined(_WIN32) && !defined(UNDER_CE) +int curlx_fseek(void *stream, curl_off_t offset, int whence); + +#ifdef _WIN32 +#ifndef CURL_WINDOWS_UWP +HANDLE curlx_CreateFile(const char *filename, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile); +#endif /* !CURL_WINDOWS_UWP */ FILE *curlx_win32_fopen(const char *filename, const char *mode); +FILE *curlx_win32_freopen(const char *filename, const char *mode, FILE *fh); int curlx_win32_stat(const char *path, struct_stat *buffer); int curlx_win32_open(const char *filename, int oflag, ...); -#define CURLX_FOPEN_LOW(fname, mode) curlx_win32_fopen(fname, mode) -#define curlx_stat(fname, stp) curlx_win32_stat(fname, stp) -#define curlx_open curlx_win32_open +int curlx_win32_rename(const char *oldpath, const char *newpath); +#define CURLX_FOPEN_LOW(fname, mode) curlx_win32_fopen(fname, mode) +#define CURLX_FREOPEN_LOW(fname, mode, fh) curlx_win32_freopen(fname, mode, fh) +#define curlx_stat(fname, stp) curlx_win32_stat(fname, stp) +#define curlx_open curlx_win32_open +#define curlx_rename curlx_win32_rename #else -#define CURLX_FOPEN_LOW fopen -#define curlx_stat(fname, stp) stat(fname, stp) -#define curlx_open open +#define CURLX_FOPEN_LOW fopen +#define CURLX_FREOPEN_LOW freopen +#define curlx_stat(fname, stp) stat(fname, stp) +#define curlx_open open +#define curlx_rename rename #endif #ifdef CURLDEBUG -#define curlx_fopen(file,mode) curl_dbg_fopen(file,mode,__LINE__,__FILE__) -#define curlx_fdopen(file,mode) curl_dbg_fdopen(file,mode,__LINE__,__FILE__) -#define curlx_fclose(file) curl_dbg_fclose(file,__LINE__,__FILE__) +#define curlx_fopen(file, mode) curl_dbg_fopen(file, mode, __LINE__, __FILE__) +#define curlx_freopen(file, mode, fh) \ + curl_dbg_freopen(file, mode, fh, __LINE__, __FILE__) +#define curlx_fdopen(file, mode) \ + curl_dbg_fdopen(file, mode, __LINE__, __FILE__) +#define curlx_fclose(file) curl_dbg_fclose(file, __LINE__, __FILE__) #else #define curlx_fopen CURLX_FOPEN_LOW +#define curlx_freopen CURLX_FREOPEN_LOW #define curlx_fdopen fdopen #define curlx_fclose fclose #endif diff --git a/lib/curlx/inet_ntop.c b/lib/curlx/inet_ntop.c index 884cfb79c2d8..e3dfdc93d186 100644 --- a/lib/curlx/inet_ntop.c +++ b/lib/curlx/inet_ntop.c @@ -32,6 +32,8 @@ #endif #include "inet_ntop.h" +#include "snprintf.h" +#include "strcopy.h" #define IN6ADDRSZ 16 /* #define INADDRSZ 4 */ @@ -61,24 +63,23 @@ static char *inet_ntop4(const unsigned char *src, char *dst, size_t size) DEBUGASSERT(size >= 16); - /* this sprintf() does not overflow the buffer. Avoids snprintf to work more - widely. Avoids the msnprintf family to work as a curlx function. */ - (void)(sprintf)(tmp, "%d.%d.%d.%d", - ((int)((unsigned char)src[0])) & 0xff, - ((int)((unsigned char)src[1])) & 0xff, - ((int)((unsigned char)src[2])) & 0xff, - ((int)((unsigned char)src[3])) & 0xff); + /* this snprintf() does not overflow the buffer. */ + SNPRINTF(tmp, sizeof(tmp), "%d.%d.%d.%d", + ((int)((unsigned char)src[0])) & 0xff, + ((int)((unsigned char)src[1])) & 0xff, + ((int)((unsigned char)src[2])) & 0xff, + ((int)((unsigned char)src[3])) & 0xff); len = strlen(tmp); if(len == 0 || len >= size) { #ifdef USE_WINSOCK - CURL_SETERRNO(WSAEINVAL); + errno = WSAEINVAL; #else - CURL_SETERRNO(ENOSPC); + errno = ENOSPC; #endif return NULL; } - strcpy(dst, tmp); + curlx_strcopy(dst, size, tmp, len); return dst; } @@ -109,17 +110,18 @@ static char *inet_ntop6(const unsigned char *src, char *dst, size_t size) */ memset(words, '\0', sizeof(words)); for(i = 0; i < IN6ADDRSZ; i++) - words[i/2] |= ((unsigned int)src[i] << ((1 - (i % 2)) << 3)); + words[i / 2] |= ((unsigned int)src[i] << ((1 - (i % 2)) << 3)); best.base = -1; - cur.base = -1; + cur.base = -1; best.len = 0; cur.len = 0; for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { if(words[i] == 0) { if(cur.base == -1) { - cur.base = i; cur.len = 1; + cur.base = i; + cur.len = 1; } else cur.len++; @@ -152,7 +154,7 @@ static char *inet_ntop6(const unsigned char *src, char *dst, size_t size) /* Is this address an encapsulated IPv4? */ if(i == 6 && best.base == 0 && - (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { if(!inet_ntop4(src + 12, tp, sizeof(tmp) - (tp - tmp))) { return NULL; } @@ -160,7 +162,7 @@ static char *inet_ntop6(const unsigned char *src, char *dst, size_t size) break; } else { - /* Lower-case digits. Can't use the set from mprintf.c since this + /* Lower-case digits. Cannot use the set from mprintf.c since this needs to work as a curlx function */ static const unsigned char ldigits[] = "0123456789abcdef"; @@ -182,17 +184,17 @@ static char *inet_ntop6(const unsigned char *src, char *dst, size_t size) *tp++ = ':'; *tp++ = '\0'; - /* Check for overflow, copy, and we are done. - */ + /* Check for overflow, copy, and we are done. */ if((size_t)(tp - tmp) > size) { #ifdef USE_WINSOCK - CURL_SETERRNO(WSAEINVAL); + errno = WSAEINVAL; #else - CURL_SETERRNO(ENOSPC); + errno = ENOSPC; #endif return NULL; } - strcpy(dst, tmp); + + curlx_strcopy(dst, size, tmp, strlen(tmp)); return dst; } @@ -215,8 +217,8 @@ char *curlx_inet_ntop(int af, const void *src, char *buf, size_t size) case AF_INET6: return inet_ntop6((const unsigned char *)src, buf, size); default: - CURL_SETERRNO(SOCKEAFNOSUPPORT); + errno = SOCKEAFNOSUPPORT; return NULL; } } -#endif /* HAVE_INET_NTOP */ +#endif /* HAVE_INET_NTOP */ diff --git a/lib/curlx/inet_ntop.h b/lib/curlx/inet_ntop.h index 490f49e8a195..79cdc9e2afea 100644 --- a/lib/curlx/inet_ntop.h +++ b/lib/curlx/inet_ntop.h @@ -37,11 +37,11 @@ #include #endif #ifdef __AMIGA__ -#define curlx_inet_ntop(af,addr,buf,size) \ +#define curlx_inet_ntop(af, addr, buf, size) \ (char *)inet_ntop(af, CURL_UNCONST(addr), (unsigned char *)buf, \ (curl_socklen_t)(size)) #else -#define curlx_inet_ntop(af,addr,buf,size) \ +#define curlx_inet_ntop(af, addr, buf, size) \ inet_ntop(af, addr, buf, (curl_socklen_t)(size)) #endif #else diff --git a/lib/curlx/inet_pton.c b/lib/curlx/inet_pton.c index d2b39ae9f1a7..8d356bb3d447 100644 --- a/lib/curlx/inet_pton.c +++ b/lib/curlx/inet_pton.c @@ -19,7 +19,7 @@ */ #include "../curl_setup.h" -#include "../curl_ctype.h" + #include "strparse.h" #ifndef HAVE_INET_PTON @@ -54,8 +54,8 @@ * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. */ -static int inet_pton4(const char *src, unsigned char *dst); -static int inet_pton6(const char *src, unsigned char *dst); +static int inet_pton4(const char *src, unsigned char *dst); +static int inet_pton6(const char *src, unsigned char *dst); /* int * inet_pton(af, src, dst) @@ -73,8 +73,7 @@ static int inet_pton6(const char *src, unsigned char *dst); * author: * Paul Vixie, 1996. */ -int -curlx_inet_pton(int af, const char *src, void *dst) +int curlx_inet_pton(int af, const char *src, void *dst) { switch(af) { case AF_INET: @@ -82,7 +81,7 @@ curlx_inet_pton(int af, const char *src, void *dst) case AF_INET6: return inet_pton6(src, (unsigned char *)dst); default: - CURL_SETERRNO(SOCKEAFNOSUPPORT); + errno = SOCKEAFNOSUPPORT; return -1; } /* NOTREACHED */ @@ -98,8 +97,7 @@ curlx_inet_pton(int af, const char *src, void *dst) * author: * Paul Vixie, 1996. */ -static int -inet_pton4(const char *src, unsigned char *dst) +static int inet_pton4(const char *src, unsigned char *dst) { int saw_digit, octets, ch; unsigned char tmp[INADDRSZ], *tp; @@ -151,8 +149,7 @@ inet_pton4(const char *src, unsigned char *dst) * author: * Paul Vixie, 1996. */ -static int -inet_pton6(const char *src, unsigned char *dst) +static int inet_pton6(const char *src, unsigned char *dst) { unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp; const char *curtok; @@ -172,7 +169,7 @@ inet_pton6(const char *src, unsigned char *dst) while((ch = *src++) != '\0') { if(ISXDIGIT(ch)) { val <<= 4; - val |= Curl_hexval(ch); + val |= curlx_hexval(ch); if(++saw_xdigit > 4) return 0; continue; @@ -187,14 +184,14 @@ inet_pton6(const char *src, unsigned char *dst) } if(tp + INT16SZ > endp) return 0; - *tp++ = (unsigned char) ((val >> 8) & 0xff); - *tp++ = (unsigned char) (val & 0xff); + *tp++ = (unsigned char)((val >> 8) & 0xff); + *tp++ = (unsigned char)(val & 0xff); saw_xdigit = 0; val = 0; continue; } if(ch == '.' && ((tp + INADDRSZ) <= endp) && - inet_pton4(curtok, tp) > 0) { + inet_pton4(curtok, tp) > 0) { tp += INADDRSZ; saw_xdigit = 0; break; /* '\0' was seen by inet_pton4(). */ @@ -204,8 +201,8 @@ inet_pton6(const char *src, unsigned char *dst) if(saw_xdigit) { if(tp + INT16SZ > endp) return 0; - *tp++ = (unsigned char) ((val >> 8) & 0xff); - *tp++ = (unsigned char) (val & 0xff); + *tp++ = (unsigned char)((val >> 8) & 0xff); + *tp++ = (unsigned char)(val & 0xff); } if(colonp) { /* diff --git a/lib/curlx/inet_pton.h b/lib/curlx/inet_pton.h index a9ad24c9447f..a52ef145dac5 100644 --- a/lib/curlx/inet_pton.h +++ b/lib/curlx/inet_pton.h @@ -37,9 +37,11 @@ #include #endif #ifdef __AMIGA__ -#define curlx_inet_pton(x,y,z) inet_pton(x,(unsigned char *)CURL_UNCONST(y),z) +#define curlx_inet_pton(x, y, z) \ + inet_pton(x, (unsigned char *)CURL_UNCONST(y), z) #else -#define curlx_inet_pton(x,y,z) inet_pton(x,y,z) +#define curlx_inet_pton(x, y, z) \ + inet_pton(x, y, z) #endif #else int curlx_inet_pton(int, const char *, void *); diff --git a/lib/curlx/multibyte.c b/lib/curlx/multibyte.c index 9e60edf7e3e2..71170df2c549 100644 --- a/lib/curlx/multibyte.c +++ b/lib/curlx/multibyte.c @@ -22,17 +22,9 @@ * ***************************************************************************/ -/* - * This file is 'mem-include-scan' clean, which means its memory allocations - * are not tracked by the curl memory tracker memdebug, so they must not use - * `CURLDEBUG` macro replacements in memdebug.h for free, malloc, etc. To avoid - * these macro replacements, wrap the names in parentheses to call the original - * versions: `ptr = (malloc)(123)`, `(free)(ptr)`, etc. - */ - #include "../curl_setup.h" -#ifdef _WIN32 +#if defined(_WIN32) && defined(UNICODE) #include "multibyte.h" @@ -48,11 +40,11 @@ wchar_t *curlx_convert_UTF8_to_wchar(const char *str_utf8) int str_w_len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, str_utf8, -1, NULL, 0); if(str_w_len > 0) { - str_w = (malloc)(str_w_len * sizeof(wchar_t)); + str_w = curlx_malloc(str_w_len * sizeof(wchar_t)); if(str_w) { if(MultiByteToWideChar(CP_UTF8, 0, str_utf8, -1, str_w, str_w_len) == 0) { - (free)(str_w); + curlx_free(str_w); return NULL; } } @@ -70,11 +62,11 @@ char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w) int bytes = WideCharToMultiByte(CP_UTF8, 0, str_w, -1, NULL, 0, NULL, NULL); if(bytes > 0) { - str_utf8 = (malloc)(bytes); + str_utf8 = curlx_malloc(bytes); if(str_utf8) { if(WideCharToMultiByte(CP_UTF8, 0, str_w, -1, str_utf8, bytes, NULL, NULL) == 0) { - (free)(str_utf8); + curlx_free(str_utf8); return NULL; } } @@ -84,4 +76,4 @@ char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w) return str_utf8; } -#endif /* _WIN32 */ +#endif /* _WIN32 && UNICODE */ diff --git a/lib/curlx/multibyte.h b/lib/curlx/multibyte.h index c60ce258c9bc..26da0f0843e0 100644 --- a/lib/curlx/multibyte.h +++ b/lib/curlx/multibyte.h @@ -26,35 +26,27 @@ #include "../curl_setup.h" #ifdef _WIN32 -/* MultiByte conversions using Windows kernel32 library. */ -wchar_t *curlx_convert_UTF8_to_wchar(const char *str_utf8); -char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w); -#endif /* * Macros curlx_convert_UTF8_to_tchar(), curlx_convert_tchar_to_UTF8() - * and curlx_unicodefree() main purpose is to minimize the number of - * preprocessor conditional directives needed by code using these - * to differentiate Unicode from non-Unicode builds. + * main purpose is to minimize the number of preprocessor conditional + * directives needed by code using these to differentiate Unicode from + * non-Unicode builds. * * In the case of a non-Unicode build the tchar strings are char strings that * are duplicated via strdup and remain in whatever the passed in encoding is, * which is assumed to be UTF-8 but may be other encoding. Therefore the * significance of the conversion functions is primarily for Unicode builds. - * - * Allocated memory should be free'd with curlx_unicodefree(). - * - * Note: Because these are curlx functions their memory usage is not tracked - * by the curl memory tracker memdebug. you will notice that curlx - * function-like macros call free and strdup in parentheses, eg (strdup)(ptr), - * and that is to ensure that the curl memdebug override macros do not replace - * them. */ -#if defined(UNICODE) && defined(_WIN32) +#ifdef UNICODE -#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)) +/* MultiByte conversions using Windows kernel32 library. */ +wchar_t *curlx_convert_UTF8_to_wchar(const char *str_utf8); +char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w); + +#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) typedef union { unsigned short *tchar_ptr; @@ -63,10 +55,10 @@ typedef union { const unsigned short *const_tbyte_ptr; } xcharp_u; -#else +#else /* !UNICODE */ -#define curlx_convert_UTF8_to_tchar(ptr) (strdup)(ptr) -#define curlx_convert_tchar_to_UTF8(ptr) (strdup)(ptr) +#define curlx_convert_UTF8_to_tchar(ptr) curlx_strdup(ptr) +#define curlx_convert_tchar_to_UTF8(ptr) curlx_strdup(ptr) typedef union { char *tchar_ptr; @@ -75,9 +67,7 @@ typedef union { const unsigned char *const_tbyte_ptr; } xcharp_u; -#endif /* UNICODE && _WIN32 */ - -/* the purpose of this macro is to free() without being traced by memdebug */ -#define curlx_unicodefree(ptr) (free)(CURL_UNCONST(ptr)) +#endif /* UNICODE */ +#endif /* _WIN32 */ #endif /* HEADER_CURL_MULTIBYTE_H */ diff --git a/lib/curlx/nonblock.c b/lib/curlx/nonblock.c index b944f9546bb5..23eb8c0e3ab2 100644 --- a/lib/curlx/nonblock.c +++ b/lib/curlx/nonblock.c @@ -88,6 +88,6 @@ int curlx_nonblock(curl_socket_t sockfd, /* operate on this */ return setsockopt(sockfd, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)); #else -# error "no non-blocking method was found/used/set" +#error "no non-blocking method was found/used/set" #endif } diff --git a/lib/curlx/nonblock.h b/lib/curlx/nonblock.h index 4a1a6151f248..ee2cd286a7e9 100644 --- a/lib/curlx/nonblock.h +++ b/lib/curlx/nonblock.h @@ -24,8 +24,6 @@ * ***************************************************************************/ -#include /* for curl_socket_t */ - int curlx_nonblock(curl_socket_t sockfd, /* operate on this */ int nonblock /* TRUE or FALSE */); diff --git a/lib/speedcheck.h b/lib/curlx/snprintf.h similarity index 75% rename from lib/speedcheck.h rename to lib/curlx/snprintf.h index f54365cadfac..266ea137fae6 100644 --- a/lib/speedcheck.h +++ b/lib/curlx/snprintf.h @@ -1,5 +1,3 @@ -#ifndef HEADER_CURL_SPEEDCHECK_H -#define HEADER_CURL_SPEEDCHECK_H /*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | @@ -24,12 +22,15 @@ * ***************************************************************************/ -#include "curl_setup.h" +/* Raw snprintf() for curlx */ -#include "curlx/timeval.h" -struct Curl_easy; -void Curl_speedinit(struct Curl_easy *data); -CURLcode Curl_speedcheck(struct Curl_easy *data, - struct curltime now); - -#endif /* HEADER_CURL_SPEEDCHECK_H */ +#ifdef WITHOUT_LIBCURL /* when built for the test servers */ +#if defined(_MSC_VER) && (_MSC_VER < 1900) /* adjust for old MSVC */ +#define SNPRINTF _snprintf +#else +#define SNPRINTF snprintf +#endif +#else /* !WITHOUT_LIBCURL */ +#include +#define SNPRINTF curl_msnprintf +#endif /* WITHOUT_LIBCURL */ diff --git a/lib/vtls/mbedtls_threadlock.h b/lib/curlx/strcopy.c similarity index 55% rename from lib/vtls/mbedtls_threadlock.h rename to lib/curlx/strcopy.c index 9402af6e415a..7ca1b9a05771 100644 --- a/lib/vtls/mbedtls_threadlock.h +++ b/lib/curlx/strcopy.c @@ -1,5 +1,3 @@ -#ifndef HEADER_CURL_MBEDTLS_THREADLOCK_H -#define HEADER_CURL_MBEDTLS_THREADLOCK_H /*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | @@ -8,7 +6,6 @@ * \___|\___/|_| \_\_____| * * Copyright (C) Daniel Stenberg, , et al. - * Copyright (C) Hoi-Ho Chan, * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -25,26 +22,28 @@ * ***************************************************************************/ #include "../curl_setup.h" +#include "strcopy.h" -#ifdef USE_MBEDTLS - -#if (defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \ - defined(_WIN32) - -int Curl_mbedtlsthreadlock_thread_setup(void); -int Curl_mbedtlsthreadlock_thread_cleanup(void); -int Curl_mbedtlsthreadlock_lock_function(int n); -int Curl_mbedtlsthreadlock_unlock_function(int n); - -#else - -#define Curl_mbedtlsthreadlock_thread_setup() 1 -#define Curl_mbedtlsthreadlock_thread_cleanup() 1 -#define Curl_mbedtlsthreadlock_lock_function(x) 1 -#define Curl_mbedtlsthreadlock_unlock_function(x) 1 - -#endif /* (USE_THREADS_POSIX && HAVE_PTHREAD_H) || _WIN32 */ - -#endif /* USE_MBEDTLS */ - -#endif /* HEADER_CURL_MBEDTLS_THREADLOCK_H */ +/* + * curlx_strcopy() is a replacement for strcpy(). + * + * Provide the target buffer @dest and size of the target buffer @dsize, If + * the source string @src with its *string length* @slen fits in the target + * buffer it will be copied there - including storing a null terminator. + * + * If the target buffer is too small, the copy is not performed but if the + * target buffer has a non-zero size it will get a null terminator stored. + */ +void curlx_strcopy(char *dest, /* destination buffer */ + size_t dsize, /* size of target buffer */ + const char *src, /* source string */ + size_t slen) /* length of source string to copy */ +{ + DEBUGASSERT(slen < dsize); + if(slen < dsize) { + memcpy(dest, src, slen); + dest[slen] = 0; + } + else if(dsize) + dest[0] = 0; +} diff --git a/lib/curl_mem_undef.h b/lib/curlx/strcopy.h similarity index 78% rename from lib/curl_mem_undef.h rename to lib/curlx/strcopy.h index 2be114cbd5e6..d671149cb8fc 100644 --- a/lib/curl_mem_undef.h +++ b/lib/curlx/strcopy.h @@ -1,3 +1,5 @@ +#ifndef HEADER_CURLX_STRCOPY_H +#define HEADER_CURLX_STRCOPY_H /*************************************************************************** * _ _ ____ _ * Project ___| | | | _ \| | @@ -22,16 +24,9 @@ * ***************************************************************************/ -/* Unset redefined system symbols. */ +void curlx_strcopy(char *dest, + size_t dsize, /* size of target buffer */ + const char *src, + size_t slen); /* length of string to copy */ -#undef strdup -#undef malloc -#undef calloc -#undef realloc -#undef free -#ifdef _WIN32 -#undef Curl_tcsdup -#endif - -#undef HEADER_CURL_MEMORY_H -#undef HEADER_CURL_MEMDEBUG_H +#endif /* HEADER_CURLX_STRCOPY_H */ diff --git a/lib/curlx/strerr.c b/lib/curlx/strerr.c index e5227554e563..addafd2897b6 100644 --- a/lib/curlx/strerr.c +++ b/lib/curlx/strerr.c @@ -32,35 +32,17 @@ # endif #endif -#include - -#ifndef WITHOUT_LIBCURL -#include -#define SNPRINTF curl_msnprintf -#else -/* when built for the test servers */ - -/* adjust for old MSVC */ -#if defined(_MSC_VER) && (_MSC_VER < 1900) -#define SNPRINTF _snprintf -#else -#define SNPRINTF snprintf -#endif -#endif /* !WITHOUT_LIBCURL */ - #include "winapi.h" +#include "snprintf.h" #include "strerr.h" -/* The last 2 #include files should be in this order */ -#include "../curl_memory.h" -#include "../memdebug.h" +#include "strcopy.h" #ifdef USE_WINSOCK /* This is a helper function for curlx_strerror that converts Winsock error * codes (WSAGetLastError) to error messages. * Returns NULL if no error message was found for error code. */ -static const char * -get_winsock_error(int err, char *buf, size_t len) +static const char *get_winsock_error(int err, char *buf, size_t len) { #ifndef CURL_DISABLE_VERBOSE_STRINGS const char *p; @@ -243,8 +225,7 @@ get_winsock_error(int err, char *buf, size_t len) return NULL; } alen = strlen(p); - if(alen < len) - strcpy(buf, p); + curlx_strcopy(buf, len, p, alen); return buf; #endif } @@ -287,20 +268,12 @@ const char *curlx_strerror(int err, char *buf, size_t buflen) *buf = '\0'; #ifdef _WIN32 -#ifndef UNDER_CE - /* 'sys_nerr' is the maximum errno number, it is not widely portable */ - if(err >= 0 && err < sys_nerr) - SNPRINTF(buf, buflen, "%s", sys_errlist[err]); - else -#endif - { - if( + if((!strerror_s(buf, buflen, err) || !strcmp(buf, "Unknown error")) && #ifdef USE_WINSOCK - !get_winsock_error(err, buf, buflen) && + !get_winsock_error(err, buf, buflen) && #endif - !curlx_get_winapi_error((DWORD)err, buf, buflen)) - SNPRINTF(buf, buflen, "Unknown error %d (%#x)", err, err); - } + !curlx_get_winapi_error((DWORD)err, buf, buflen)) + SNPRINTF(buf, buflen, "Unknown error %d (%#x)", err, err); #else /* !_WIN32 */ #if defined(HAVE_STRERROR_R) && defined(HAVE_POSIX_STRERROR_R) @@ -350,7 +323,7 @@ const char *curlx_strerror(int err, char *buf, size_t buflen) *p = '\0'; if(errno != old_errno) - CURL_SETERRNO(old_errno); + errno = old_errno; #ifdef _WIN32 if(old_win_err != GetLastError()) diff --git a/lib/curlx/strparse.c b/lib/curlx/strparse.c index a29d8be2fdb7..66c749b91665 100644 --- a/lib/curlx/strparse.c +++ b/lib/curlx/strparse.c @@ -24,10 +24,6 @@ #include "strparse.h" -#ifndef WITHOUT_LIBCURL -#include /* for curl_strnequal() */ -#endif - void curlx_str_init(struct Curl_str *out) { out->str = NULL; @@ -66,8 +62,7 @@ int curlx_str_until(const char **linep, struct Curl_str *out, /* Get a word until the first space or end of string. At least one byte long. return non-zero on error */ -int curlx_str_word(const char **linep, struct Curl_str *out, - const size_t max) +int curlx_str_word(const char **linep, struct Curl_str *out, const size_t max) { return curlx_str_until(linep, out, max, ' '); } @@ -95,7 +90,6 @@ int curlx_str_untilnl(const char **linep, struct Curl_str *out, return STRE_OK; } - /* Get a "quoted" word. No escaping possible. return non-zero on error */ int curlx_str_quotedword(const char **linep, struct Curl_str *out, @@ -141,13 +135,13 @@ int curlx_str_singlespace(const char **linep) } /* given an ASCII character and max ascii, return TRUE if valid */ -#define valid_digit(x,m) \ - (((x) >= '0') && ((x) <= m) && Curl_hexasciitable[(x)-'0']) +#define valid_digit(x, m) \ + (((x) >= '0') && ((x) <= m) && curlx_hexasciitable[(x) - '0']) /* We use 16 for the zero index (and the necessary bitwise AND in the loop) to be able to have a non-zero value there to make valid_digit() able to use the info */ -const unsigned char Curl_hexasciitable[] = { +const unsigned char curlx_hexasciitable[] = { 16, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* 0x30: 0 - 9 */ 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15, /* 0x41: A - F */ @@ -173,7 +167,7 @@ static int str_num_base(const char **linep, curl_off_t *nump, curl_off_t max, if(max < base) { /* special-case low max scenario because check needs to be different */ do { - int n = Curl_hexval(*p++); + int n = curlx_hexval(*p++); num = num * base + n; if(num > max) return STRE_OVERFLOW; @@ -181,7 +175,7 @@ static int str_num_base(const char **linep, curl_off_t *nump, curl_off_t max, } else { do { - int n = Curl_hexval(*p++); + int n = curlx_hexval(*p++); if(num > ((max - n) / base)) return STRE_OVERFLOW; num = num * base + n; diff --git a/lib/curlx/strparse.h b/lib/curlx/strparse.h index 6a0bf28d6cbc..27fea2957e09 100644 --- a/lib/curlx/strparse.h +++ b/lib/curlx/strparse.h @@ -45,7 +45,7 @@ struct Curl_str { void curlx_str_init(struct Curl_str *out); void curlx_str_assign(struct Curl_str *out, const char *str, size_t len); -#define curlx_str(x) ((x)->str) +#define curlx_str(x) ((x)->str) #define curlx_strlen(x) ((x)->len) /* Get a word until the first space @@ -106,7 +106,7 @@ void curlx_str_passblanks(const char **linep); returns 10. THIS ONLY WORKS ON VALID HEXADECIMAL LETTER INPUT. Verify before calling this! */ -extern const unsigned char Curl_hexasciitable[]; -#define Curl_hexval(x) (unsigned char)(Curl_hexasciitable[(x) - '0'] & 0x0f) +extern const unsigned char curlx_hexasciitable[]; +#define curlx_hexval(x) (unsigned char)(curlx_hexasciitable[(x) - '0'] & 0x0f) #endif /* HEADER_CURL_STRPARSE_H */ diff --git a/lib/curlx/timediff.c b/lib/curlx/timediff.c index a90da961ab83..58a4dfd3033c 100644 --- a/lib/curlx/timediff.c +++ b/lib/curlx/timediff.c @@ -24,8 +24,6 @@ #include "timediff.h" -#include - /* * Converts number of milliseconds into a timeval structure. * @@ -84,5 +82,5 @@ struct timeval *curlx_mstotv(struct timeval *tv, timediff_t ms) */ timediff_t curlx_tvtoms(struct timeval *tv) { - return (tv->tv_sec*1000) + (timediff_t)(tv->tv_usec/1000); + return (tv->tv_sec * 1000) + (timediff_t)(tv->tv_usec / 1000); } diff --git a/lib/curlx/timeval.c b/lib/curlx/timeval.c index bd8b9bcee27b..08cc2aba5e5b 100644 --- a/lib/curlx/timeval.c +++ b/lib/curlx/timeval.c @@ -26,7 +26,6 @@ #ifdef _WIN32 -#include #include "version_win32.h" #include "../system_win32.h" @@ -47,9 +46,8 @@ void curlx_now_init(void) } /* In case of bug fix this function has a counterpart in tool_util.c */ -struct curltime curlx_now(void) +void curlx_pnow(struct curltime *pnow) { - struct curltime now; bool isVistaOrGreater; isVistaOrGreater = Curl_isVistaOrGreater; if(isVistaOrGreater) { /* QPC timer might have issues pre-Vista */ @@ -58,8 +56,8 @@ struct curltime curlx_now(void) freq = Curl_freq; DEBUGASSERT(freq.QuadPart); QueryPerformanceCounter(&count); - now.tv_sec = (time_t)(count.QuadPart / freq.QuadPart); - now.tv_usec = (int)((count.QuadPart % freq.QuadPart) * 1000000 / + pnow->tv_sec = (time_t)(count.QuadPart / freq.QuadPart); + pnow->tv_usec = (int)((count.QuadPart % freq.QuadPart) * 1000000 / freq.QuadPart); } else { @@ -73,16 +71,15 @@ struct curltime curlx_now(void) #pragma warning(pop) #endif - now.tv_sec = (time_t)(milliseconds / 1000); - now.tv_usec = (int)((milliseconds % 1000) * 1000); + pnow->tv_sec = (time_t)(milliseconds / 1000); + pnow->tv_usec = (int)((milliseconds % 1000) * 1000); } - return now; } -#elif defined(HAVE_CLOCK_GETTIME_MONOTONIC) || \ +#elif defined(HAVE_CLOCK_GETTIME_MONOTONIC) || \ defined(HAVE_CLOCK_GETTIME_MONOTONIC_RAW) -struct curltime curlx_now(void) +void curlx_pnow(struct curltime *pnow) { /* ** clock_gettime() is granted to be increased monotonically when the @@ -91,10 +88,6 @@ struct curltime curlx_now(void) ** in any case the time starting point does not change once that the ** system has started up. */ -#ifdef HAVE_GETTIMEOFDAY - struct timeval now; -#endif - struct curltime cnow; struct timespec tsnow; /* @@ -103,7 +96,7 @@ struct curltime curlx_now(void) ** called on unsupported OS version. */ #if defined(__APPLE__) && defined(HAVE_BUILTIN_AVAILABLE) && \ - (HAVE_BUILTIN_AVAILABLE == 1) + (HAVE_BUILTIN_AVAILABLE == 1) bool have_clock_gettime = FALSE; if(__builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *)) have_clock_gettime = TRUE; @@ -111,25 +104,25 @@ struct curltime curlx_now(void) #ifdef HAVE_CLOCK_GETTIME_MONOTONIC_RAW if( -#if defined(__APPLE__) && defined(HAVE_BUILTIN_AVAILABLE) && \ - (HAVE_BUILTIN_AVAILABLE == 1) +#if defined(__APPLE__) && defined(HAVE_BUILTIN_AVAILABLE) && \ + (HAVE_BUILTIN_AVAILABLE == 1) have_clock_gettime && #endif (clock_gettime(CLOCK_MONOTONIC_RAW, &tsnow) == 0)) { - cnow.tv_sec = tsnow.tv_sec; - cnow.tv_usec = (int)(tsnow.tv_nsec / 1000); + pnow->tv_sec = tsnow.tv_sec; + pnow->tv_usec = (int)(tsnow.tv_nsec / 1000); } else #endif if( #if defined(__APPLE__) && defined(HAVE_BUILTIN_AVAILABLE) && \ - (HAVE_BUILTIN_AVAILABLE == 1) + (HAVE_BUILTIN_AVAILABLE == 1) have_clock_gettime && #endif (clock_gettime(CLOCK_MONOTONIC, &tsnow) == 0)) { - cnow.tv_sec = tsnow.tv_sec; - cnow.tv_usec = (int)(tsnow.tv_nsec / 1000); + pnow->tv_sec = tsnow.tv_sec; + pnow->tv_usec = (int)(tsnow.tv_nsec / 1000); } /* ** Even when the configure process has truly detected monotonic clock @@ -138,17 +131,17 @@ struct curltime curlx_now(void) */ #ifdef HAVE_GETTIMEOFDAY else { + struct timeval now; (void)gettimeofday(&now, NULL); - cnow.tv_sec = now.tv_sec; - cnow.tv_usec = (int)now.tv_usec; + pnow->tv_sec = now.tv_sec; + pnow->tv_usec = (int)now.tv_usec; } #else else { - cnow.tv_sec = time(NULL); - cnow.tv_usec = 0; + pnow->tv_sec = time(NULL); + pnow->tv_usec = 0; } #endif - return cnow; } #elif defined(HAVE_MACH_ABSOLUTE_TIME) @@ -156,7 +149,7 @@ struct curltime curlx_now(void) #include #include -struct curltime curlx_now(void) +void curlx_pnow(struct curltime *pnow) { /* ** Monotonic timer on macOS is provided by mach_absolute_time(), which @@ -165,7 +158,6 @@ struct curltime curlx_now(void) ** mach_timebase_info(). */ static mach_timebase_info_data_t timebase; - struct curltime cnow; uint64_t usecs; if(timebase.denom == 0) @@ -176,15 +168,13 @@ struct curltime curlx_now(void) usecs /= timebase.denom; usecs /= 1000; - cnow.tv_sec = usecs / 1000000; - cnow.tv_usec = (int)(usecs % 1000000); - - return cnow; + pnow->tv_sec = usecs / 1000000; + pnow->tv_usec = (int)(usecs % 1000000); } #elif defined(HAVE_GETTIMEOFDAY) -struct curltime curlx_now(void) +void curlx_pnow(struct curltime *pnow) { /* ** gettimeofday() is not granted to be increased monotonically, due to @@ -192,68 +182,121 @@ struct curltime curlx_now(void) ** forward or backward in time. */ struct timeval now; - struct curltime ret; (void)gettimeofday(&now, NULL); - ret.tv_sec = now.tv_sec; - ret.tv_usec = (int)now.tv_usec; - return ret; + pnow->tv_sec = now.tv_sec; + pnow->tv_usec = (int)now.tv_usec; } #else -struct curltime curlx_now(void) +void curlx_pnow(struct curltime *pnow) { /* ** time() returns the value of time in seconds since the Epoch. */ - struct curltime now; - now.tv_sec = time(NULL); - now.tv_usec = 0; - return now; + pnow->tv_sec = time(NULL); + pnow->tv_usec = 0; } #endif +struct curltime curlx_now(void) +{ + struct curltime now; + curlx_pnow(&now); + return now; +} + /* * Returns: time difference in number of milliseconds. For too large diffs it * returns max value. * * @unittest: 1323 */ -timediff_t curlx_timediff(struct curltime newer, struct curltime older) +timediff_t curlx_ptimediff_ms(const struct curltime *newer, + const struct curltime *older) { - timediff_t diff = (timediff_t)newer.tv_sec-older.tv_sec; - if(diff >= (TIMEDIFF_T_MAX/1000)) + timediff_t diff = (timediff_t)newer->tv_sec - older->tv_sec; + if(diff >= (TIMEDIFF_T_MAX / 1000)) return TIMEDIFF_T_MAX; - else if(diff <= (TIMEDIFF_T_MIN/1000)) + else if(diff <= (TIMEDIFF_T_MIN / 1000)) return TIMEDIFF_T_MIN; - return diff * 1000 + (newer.tv_usec-older.tv_usec)/1000; + return diff * 1000 + (newer->tv_usec - older->tv_usec) / 1000; +} + + +timediff_t curlx_timediff_ms(struct curltime newer, struct curltime older) +{ + return curlx_ptimediff_ms(&newer, &older); } /* * Returns: time difference in number of milliseconds, rounded up. * For too large diffs it returns max value. */ -timediff_t curlx_timediff_ceil(struct curltime newer, struct curltime older) +timediff_t curlx_timediff_ceil_ms(struct curltime newer, + struct curltime older) { - timediff_t diff = (timediff_t)newer.tv_sec-older.tv_sec; - if(diff >= (TIMEDIFF_T_MAX/1000)) + timediff_t diff = (timediff_t)newer.tv_sec - older.tv_sec; + if(diff >= (TIMEDIFF_T_MAX / 1000)) return TIMEDIFF_T_MAX; - else if(diff <= (TIMEDIFF_T_MIN/1000)) + else if(diff <= (TIMEDIFF_T_MIN / 1000)) return TIMEDIFF_T_MIN; - return diff * 1000 + (newer.tv_usec - older.tv_usec + 999)/1000; + return diff * 1000 + (newer.tv_usec - older.tv_usec + 999) / 1000; } /* * Returns: time difference in number of microseconds. For too large diffs it * returns max value. */ -timediff_t curlx_timediff_us(struct curltime newer, struct curltime older) +timediff_t curlx_ptimediff_us(const struct curltime *newer, + const struct curltime *older) { - timediff_t diff = (timediff_t)newer.tv_sec-older.tv_sec; - if(diff >= (TIMEDIFF_T_MAX/1000000)) + timediff_t diff = (timediff_t)newer->tv_sec - older->tv_sec; + if(diff >= (TIMEDIFF_T_MAX / 1000000)) return TIMEDIFF_T_MAX; - else if(diff <= (TIMEDIFF_T_MIN/1000000)) + else if(diff <= (TIMEDIFF_T_MIN / 1000000)) return TIMEDIFF_T_MIN; - return diff * 1000000 + newer.tv_usec-older.tv_usec; + return diff * 1000000 + newer->tv_usec - older->tv_usec; +} + +timediff_t curlx_timediff_us(struct curltime newer, struct curltime older) +{ + return curlx_ptimediff_us(&newer, &older); +} + +#if defined(__MINGW32__) && (__MINGW64_VERSION_MAJOR <= 3) +#include /* for _gmtime32_s(), _gmtime64_s() */ +#ifdef _USE_32BIT_TIME_T +#define gmtime_s _gmtime32_s +#else +#define gmtime_s _gmtime64_s +#endif +#endif + +/* + * curlx_gmtime() is a gmtime() replacement for portability. Do not use + * the gmtime_s(), gmtime_r() or gmtime() functions anywhere else but here. + */ +CURLcode curlx_gmtime(time_t intime, struct tm *store) +{ +#ifdef _WIN32 + if(gmtime_s(store, &intime)) /* thread-safe */ + return CURLE_BAD_FUNCTION_ARGUMENT; +#elif defined(HAVE_GMTIME_R) + const struct tm *tm; + tm = gmtime_r(&intime, store); /* thread-safe */ + if(!tm) + return CURLE_BAD_FUNCTION_ARGUMENT; +#else + const struct tm *tm; + /* !checksrc! disable BANNEDFUNC 1 */ + tm = gmtime(&intime); /* not thread-safe */ + if(tm) + *store = *tm; /* copy the pointed struct to the local copy */ + else + return CURLE_BAD_FUNCTION_ARGUMENT; +#endif + + return CURLE_OK; } diff --git a/lib/curlx/timeval.h b/lib/curlx/timeval.h index 1f8fe5e8ad1e..533e80e5e3c2 100644 --- a/lib/curlx/timeval.h +++ b/lib/curlx/timeval.h @@ -39,6 +39,7 @@ void curlx_now_init(void); #endif struct curltime curlx_now(void); +void curlx_pnow(struct curltime *pnow); /* * Make sure that the first argument (newer) is the more recent time and older @@ -46,7 +47,9 @@ struct curltime curlx_now(void); * * Returns: the time difference in number of milliseconds. */ -timediff_t curlx_timediff(struct curltime newer, struct curltime older); +timediff_t curlx_timediff_ms(struct curltime newer, struct curltime older); +timediff_t curlx_ptimediff_ms(const struct curltime *newer, + const struct curltime *older); /* * Make sure that the first argument (newer) is the more recent time and older @@ -54,7 +57,8 @@ timediff_t curlx_timediff(struct curltime newer, struct curltime older); * * Returns: the time difference in number of milliseconds, rounded up. */ -timediff_t curlx_timediff_ceil(struct curltime newer, struct curltime older); +timediff_t curlx_timediff_ceil_ms(struct curltime newer, + struct curltime older); /* * Make sure that the first argument (newer) is the more recent time and older @@ -63,5 +67,9 @@ timediff_t curlx_timediff_ceil(struct curltime newer, struct curltime older); * Returns: the time difference in number of microseconds. */ timediff_t curlx_timediff_us(struct curltime newer, struct curltime older); +timediff_t curlx_ptimediff_us(const struct curltime *newer, + const struct curltime *older); + +CURLcode curlx_gmtime(time_t intime, struct tm *store); #endif /* HEADER_CURL_TIMEVAL_H */ diff --git a/lib/curlx/version_win32.c b/lib/curlx/version_win32.c index 7e415dfe89d9..be5b13c9de3c 100644 --- a/lib/curlx/version_win32.c +++ b/lib/curlx/version_win32.c @@ -26,13 +26,7 @@ #ifdef _WIN32 -#include #include "version_win32.h" -#include "warnless.h" - -/* The last 2 #include files should be in this order */ -#include "../curl_memory.h" -#include "../memdebug.h" /* This Unicode version struct works for VerifyVersionInfoW (OSVERSIONINFOEXW) and RtlVerifyVersionInfo (RTLOSVERSIONINFOEXW) */ @@ -111,12 +105,6 @@ bool curlx_verify_windows_version(const unsigned int majorVersion, /* we are always running on PLATFORM_WINNT */ matched = FALSE; } -#elif defined(UNDER_CE) - (void)majorVersion; - (void)minorVersion; - (void)buildVersion; - (void)platform; - (void)condition; #else ULONGLONG cm = 0; struct OUR_OSVERSIONINFOEXW osver; @@ -139,7 +127,7 @@ bool curlx_verify_windows_version(const unsigned int majorVersion, #pragma clang diagnostic ignored "-Wcast-function-type-strict" #endif pRtlVerifyVersionInfo = CURLX_FUNCTION_CAST(RTLVERIFYVERSIONINFO_FN, - GetProcAddress(GetModuleHandleA("ntdll"), "RtlVerifyVersionInfo")); + GetProcAddress(GetModuleHandle(TEXT("ntdll")), "RtlVerifyVersionInfo")); #if defined(__clang__) && __clang_major__ >= 16 #pragma clang diagnostic pop #endif diff --git a/lib/curlx/wait.c b/lib/curlx/wait.c index 4e10a8297a93..f42041961b19 100644 --- a/lib/curlx/wait.c +++ b/lib/curlx/wait.c @@ -28,8 +28,6 @@ #error "We cannot compile without select() support." #endif -#include - #ifdef HAVE_SYS_SELECT_H #include #elif defined(HAVE_UNISTD_H) @@ -74,7 +72,7 @@ int curlx_wait_ms(timediff_t timeout_ms) /* prevent overflow, timeout_ms is typecast to ULONG/DWORD. */ #if TIMEDIFF_T_MAX >= ULONG_MAX if(timeout_ms >= ULONG_MAX) - timeout_ms = ULONG_MAX-1; + timeout_ms = ULONG_MAX - 1; /* do not use ULONG_MAX, because that is equal to INFINITE */ #endif Sleep((DWORD)timeout_ms); diff --git a/lib/curlx/warnless.c b/lib/curlx/warnless.c index bb636a93270f..1b3d88481ab0 100644 --- a/lib/curlx/warnless.c +++ b/lib/curlx/warnless.c @@ -27,16 +27,14 @@ #if defined(__INTEL_COMPILER) && defined(__unix__) #ifdef HAVE_NETINET_IN_H -# include +#include #endif #ifdef HAVE_ARPA_INET_H -# include +#include #endif #endif /* __INTEL_COMPILER && __unix__ */ -#include - #define CURL_MASK_UCHAR ((unsigned char)~0) #define CURL_MASK_USHORT ((unsigned short)~0) @@ -56,15 +54,15 @@ unsigned char curlx_ultouc(unsigned long ulnum) { #ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:810) /* conversion may lose significant bits */ +#pragma warning(push) +#pragma warning(disable:810) /* conversion may lose significant bits */ #endif - DEBUGASSERT(ulnum <= (unsigned long) CURL_MASK_UCHAR); - return (unsigned char)(ulnum & (unsigned long) CURL_MASK_UCHAR); + DEBUGASSERT(ulnum <= (unsigned long)CURL_MASK_UCHAR); + return (unsigned char)(ulnum & (unsigned long)CURL_MASK_UCHAR); #ifdef __INTEL_COMPILER -# pragma warning(pop) +#pragma warning(pop) #endif } @@ -75,15 +73,15 @@ unsigned char curlx_ultouc(unsigned long ulnum) int curlx_uztosi(size_t uznum) { #ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:810) /* conversion may lose significant bits */ +#pragma warning(push) +#pragma warning(disable:810) /* conversion may lose significant bits */ #endif - DEBUGASSERT(uznum <= (size_t) CURL_MASK_SINT); - return (int)(uznum & (size_t) CURL_MASK_SINT); + DEBUGASSERT(uznum <= (size_t)CURL_MASK_SINT); + return (int)(uznum & (size_t)CURL_MASK_SINT); #ifdef __INTEL_COMPILER -# pragma warning(pop) +#pragma warning(pop) #endif } @@ -94,17 +92,17 @@ int curlx_uztosi(size_t uznum) unsigned long curlx_uztoul(size_t uznum) { #ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:810) /* conversion may lose significant bits */ +#pragma warning(push) +#pragma warning(disable:810) /* conversion may lose significant bits */ #endif #if ULONG_MAX < SIZE_MAX - DEBUGASSERT(uznum <= (size_t) CURL_MASK_ULONG); + DEBUGASSERT(uznum <= (size_t)CURL_MASK_ULONG); #endif - return (unsigned long)(uznum & (size_t) CURL_MASK_ULONG); + return (unsigned long)(uznum & (size_t)CURL_MASK_ULONG); #ifdef __INTEL_COMPILER -# pragma warning(pop) +#pragma warning(pop) #endif } @@ -115,17 +113,17 @@ unsigned long curlx_uztoul(size_t uznum) unsigned int curlx_uztoui(size_t uznum) { #ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:810) /* conversion may lose significant bits */ +#pragma warning(push) +#pragma warning(disable:810) /* conversion may lose significant bits */ #endif #if UINT_MAX < SIZE_MAX - DEBUGASSERT(uznum <= (size_t) CURL_MASK_UINT); + DEBUGASSERT(uznum <= (size_t)CURL_MASK_UINT); #endif - return (unsigned int)(uznum & (size_t) CURL_MASK_UINT); + return (unsigned int)(uznum & (size_t)CURL_MASK_UINT); #ifdef __INTEL_COMPILER -# pragma warning(pop) +#pragma warning(pop) #endif } @@ -136,18 +134,18 @@ unsigned int curlx_uztoui(size_t uznum) int curlx_sltosi(long slnum) { #ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:810) /* conversion may lose significant bits */ +#pragma warning(push) +#pragma warning(disable:810) /* conversion may lose significant bits */ #endif DEBUGASSERT(slnum >= 0); #if INT_MAX < LONG_MAX - DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_SINT); + DEBUGASSERT((unsigned long)slnum <= (unsigned long)CURL_MASK_SINT); #endif - return (int)(slnum & (long) CURL_MASK_SINT); + return (int)(slnum & (long)CURL_MASK_SINT); #ifdef __INTEL_COMPILER -# pragma warning(pop) +#pragma warning(pop) #endif } @@ -158,18 +156,18 @@ int curlx_sltosi(long slnum) unsigned int curlx_sltoui(long slnum) { #ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:810) /* conversion may lose significant bits */ +#pragma warning(push) +#pragma warning(disable:810) /* conversion may lose significant bits */ #endif DEBUGASSERT(slnum >= 0); #if UINT_MAX < LONG_MAX - DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_UINT); + DEBUGASSERT((unsigned long)slnum <= (unsigned long)CURL_MASK_UINT); #endif - return (unsigned int)(slnum & (long) CURL_MASK_UINT); + return (unsigned int)(slnum & (long)CURL_MASK_UINT); #ifdef __INTEL_COMPILER -# pragma warning(pop) +#pragma warning(pop) #endif } @@ -180,16 +178,16 @@ unsigned int curlx_sltoui(long slnum) unsigned short curlx_sltous(long slnum) { #ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:810) /* conversion may lose significant bits */ +#pragma warning(push) +#pragma warning(disable:810) /* conversion may lose significant bits */ #endif DEBUGASSERT(slnum >= 0); - DEBUGASSERT((unsigned long) slnum <= (unsigned long) CURL_MASK_USHORT); - return (unsigned short)(slnum & (long) CURL_MASK_USHORT); + DEBUGASSERT((unsigned long)slnum <= (unsigned long)CURL_MASK_USHORT); + return (unsigned short)(slnum & (long)CURL_MASK_USHORT); #ifdef __INTEL_COMPILER -# pragma warning(pop) +#pragma warning(pop) #endif } @@ -200,15 +198,15 @@ unsigned short curlx_sltous(long slnum) ssize_t curlx_uztosz(size_t uznum) { #ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:810) /* conversion may lose significant bits */ +#pragma warning(push) +#pragma warning(disable:810) /* conversion may lose significant bits */ #endif - DEBUGASSERT(uznum <= (size_t) CURL_MASK_SSIZE_T); - return (ssize_t)(uznum & (size_t) CURL_MASK_SSIZE_T); + DEBUGASSERT(uznum <= (size_t)CURL_MASK_SSIZE_T); + return (ssize_t)(uznum & (size_t)CURL_MASK_SSIZE_T); #ifdef __INTEL_COMPILER -# pragma warning(pop) +#pragma warning(pop) #endif } @@ -219,15 +217,15 @@ ssize_t curlx_uztosz(size_t uznum) size_t curlx_sotouz(curl_off_t sonum) { #ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:810) /* conversion may lose significant bits */ +#pragma warning(push) +#pragma warning(disable:810) /* conversion may lose significant bits */ #endif DEBUGASSERT(sonum >= 0); - return (size_t)(sonum & (curl_off_t) CURL_MASK_USIZE_T); + return (size_t)(sonum & (curl_off_t)CURL_MASK_USIZE_T); #ifdef __INTEL_COMPILER -# pragma warning(pop) +#pragma warning(pop) #endif } @@ -238,18 +236,18 @@ size_t curlx_sotouz(curl_off_t sonum) int curlx_sztosi(ssize_t sznum) { #ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:810) /* conversion may lose significant bits */ +#pragma warning(push) +#pragma warning(disable:810) /* conversion may lose significant bits */ #endif DEBUGASSERT(sznum >= 0); #if INT_MAX < SSIZE_MAX - DEBUGASSERT((size_t) sznum <= (size_t) CURL_MASK_SINT); + DEBUGASSERT((size_t)sznum <= (size_t)CURL_MASK_SINT); #endif - return (int)(sznum & (ssize_t) CURL_MASK_SINT); + return (int)(sznum & (ssize_t)CURL_MASK_SINT); #ifdef __INTEL_COMPILER -# pragma warning(pop) +#pragma warning(pop) #endif } @@ -260,15 +258,15 @@ int curlx_sztosi(ssize_t sznum) unsigned short curlx_uitous(unsigned int uinum) { #ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:810) /* conversion may lose significant bits */ +#pragma warning(push) +#pragma warning(disable:810) /* conversion may lose significant bits */ #endif - DEBUGASSERT(uinum <= (unsigned int) CURL_MASK_USHORT); - return (unsigned short) (uinum & (unsigned int) CURL_MASK_USHORT); + DEBUGASSERT(uinum <= (unsigned int)CURL_MASK_USHORT); + return (unsigned short)(uinum & (unsigned int)CURL_MASK_USHORT); #ifdef __INTEL_COMPILER -# pragma warning(pop) +#pragma warning(pop) #endif } @@ -279,14 +277,76 @@ unsigned short curlx_uitous(unsigned int uinum) size_t curlx_sitouz(int sinum) { #ifdef __INTEL_COMPILER -# pragma warning(push) -# pragma warning(disable:810) /* conversion may lose significant bits */ +#pragma warning(push) +#pragma warning(disable:810) /* conversion may lose significant bits */ #endif DEBUGASSERT(sinum >= 0); - return (size_t) sinum; + return (size_t)sinum; #ifdef __INTEL_COMPILER -# pragma warning(pop) +#pragma warning(pop) +#endif +} + +size_t curlx_uitouz(unsigned int uinum) +{ + return (size_t)uinum; +} + +size_t curlx_sotouz_range(curl_off_t sonum, size_t uzmin, size_t uzmax) +{ + if(sonum < 0) + return uzmin; +#if SIZEOF_CURL_OFF_T > SIZEOF_SIZE_T + if(sonum > SIZE_MAX) + return uzmax; +#endif + return CURLMIN(CURLMAX((size_t)sonum, uzmin), uzmax); +} + +bool curlx_sztouz(ssize_t sznum, size_t *puznum) +{ + if(sznum < 0) { + *puznum = 0; + return FALSE; + } + *puznum = (size_t)sznum; + return TRUE; +} + +bool curlx_sotouz_fits(curl_off_t sonum, size_t *puznum) +{ + if(sonum < 0) { + *puznum = 0; + return FALSE; + } +#if SIZEOF_CURL_OFF_T > SIZEOF_SIZE_T + if(sonum > SIZE_MAX) { + *puznum = 0; + return FALSE; + } +#endif + *puznum = (size_t)sonum; + return TRUE; +} + +bool curlx_sltouz(long slnum, size_t *puznum) +{ + if(slnum < 0) { + *puznum = 0; + return FALSE; + } + /* We error in curl_setup.h if SIZEOF_LONG > SIZEOF_SIZE_T */ + *puznum = (size_t)slnum; + return TRUE; +} + +curl_off_t curlx_uztoso(size_t uznum) +{ +#if SIZEOF_SIZE_T >= SIZEOF_CURL_OFF_T + if(uznum > (size_t)CURL_OFF_T_MAX) + return CURL_OFF_T_MAX; #endif + return (curl_off_t)uznum; } diff --git a/lib/curlx/warnless.h b/lib/curlx/warnless.h index 0a0c60807340..290aaac28db4 100644 --- a/lib/curlx/warnless.h +++ b/lib/curlx/warnless.h @@ -26,12 +26,8 @@ #include "../curl_setup.h" -#ifdef USE_WINSOCK -#include /* for curl_socket_t */ -#endif - #define CURLX_FUNCTION_CAST(target_type, func) \ - (target_type)(void (*) (void))(func) + (target_type)(void (*)(void))(func) unsigned char curlx_ultouc(unsigned long ulnum); @@ -57,11 +53,24 @@ unsigned short curlx_uitous(unsigned int uinum); size_t curlx_sitouz(int sinum); -#ifdef _WIN32 -#undef read -#define read(fd, buf, count) (ssize_t)_read(fd, buf, curlx_uztoui(count)) -#undef write -#define write(fd, buf, count) (ssize_t)_write(fd, buf, curlx_uztoui(count)) -#endif +size_t curlx_uitouz(unsigned int uinum); + +/* Convert a curl_off_t to fit into size_t interval [uzmin, uzmax]. + * values outside this interval give the lower/upper bound. */ +size_t curlx_sotouz_range(curl_off_t sonum, size_t uzmin, size_t uzmax); + +/* Convert a size_t to curl_off_t, return CURL_OFF_T_MAX if too large. */ +curl_off_t curlx_uztoso(size_t uznum); + +/* Convert a ssize_t to size_t, return FALSE if negative and set 0 */ +bool curlx_sztouz(ssize_t sznum, size_t *puznum); + +/* Convert a curl_off_t to size_t, return FALSE if negative or + * too large and set 0 */ +bool curlx_sotouz_fits(curl_off_t sonum, size_t *puznum); + +/* Convert a long to size_t, return FALSE if negative or too large + * and set 0 */ +bool curlx_sltouz(long sznum, size_t *puznum); #endif /* HEADER_CURL_WARNLESS_H */ diff --git a/lib/curlx/winapi.c b/lib/curlx/winapi.c index de1218cec7f5..b46a5bf0ddf0 100644 --- a/lib/curlx/winapi.c +++ b/lib/curlx/winapi.c @@ -29,20 +29,8 @@ */ #ifdef _WIN32 #include "winapi.h" - -#ifndef WITHOUT_LIBCURL -#include -#define SNPRINTF curl_msnprintf -#else -/* when built for the test servers */ - -/* adjust for old MSVC */ -#if defined(_MSC_VER) && (_MSC_VER < 1900) -#define SNPRINTF _snprintf -#else -#define SNPRINTF snprintf -#endif -#endif /* !WITHOUT_LIBCURL */ +#include "snprintf.h" +#include "strcopy.h" /* This is a helper function for curlx_strerror that converts Windows API error * codes (GetLastError) to error messages. @@ -52,6 +40,7 @@ const char *curlx_get_winapi_error(DWORD err, char *buf, size_t buflen) { char *p; wchar_t wbuf[256]; + DWORD wlen; if(!buflen) return NULL; @@ -61,25 +50,19 @@ const char *curlx_get_winapi_error(DWORD err, char *buf, size_t buflen) /* We return the local codepage version of the error string because if it is output to the user's terminal it will likely be with functions which - expect the local codepage (eg fprintf, failf, infof). - FormatMessageW -> wcstombs is used for Windows CE compatibility. */ - if(FormatMessageW((FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS), NULL, err, - LANG_NEUTRAL, wbuf, CURL_ARRAYSIZE(wbuf), NULL)) { - size_t written = wcstombs(buf, wbuf, buflen - 1); - if(written != (size_t)-1) - buf[written] = '\0'; - else - *buf = '\0'; - } - - /* Truncate multiple lines */ - p = strchr(buf, '\n'); - if(p) { - if(p > buf && *(p-1) == '\r') - *(p-1) = '\0'; - else - *p = '\0'; + expect the local codepage (eg fprintf, failf, infof). */ + wlen = FormatMessageW((FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS), NULL, err, + LANG_NEUTRAL, wbuf, CURL_ARRAYSIZE(wbuf), NULL); + if(wlen && !wcstombs_s(NULL, buf, buflen, wbuf, wlen)) { + /* Truncate multiple lines */ + p = strchr(buf, '\n'); + if(p) { + if(p > buf && *(p - 1) == '\r') + *(p - 1) = '\0'; + else + *p = '\0'; + } } return *buf ? buf : NULL; @@ -107,18 +90,16 @@ const char *curlx_winapi_strerror(DWORD err, char *buf, size_t buflen) #if defined(__GNUC__) && __GNUC__ >= 7 #pragma GCC diagnostic pop #endif - } #else { const char *txt = (err == ERROR_SUCCESS) ? "No error" : "Error"; - if(strlen(txt) < buflen) - strcpy(buf, txt); + curlx_strcopy(buf, buflen, txt, strlen(txt)); } #endif if(errno != old_errno) - CURL_SETERRNO(old_errno); + errno = old_errno; if(old_win_err != GetLastError()) SetLastError(old_win_err); diff --git a/lib/cw-out.c b/lib/cw-out.c index 7a9274b5f21b..ad880504a8a2 100644 --- a/lib/cw-out.c +++ b/lib/cw-out.c @@ -24,21 +24,15 @@ #include "curl_setup.h" -#include - #include "urldata.h" #include "cfilters.h" -#include "headers.h" #include "multiif.h" #include "sendf.h" +#include "curl_trc.h" #include "transfer.h" #include "cw-out.h" #include "cw-pause.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - /** * OVERALL DESIGN of this client writer @@ -85,7 +79,7 @@ struct cw_out_buf { static struct cw_out_buf *cw_out_buf_create(cw_out_type otype) { - struct cw_out_buf *cwbuf = calloc(1, sizeof(*cwbuf)); + struct cw_out_buf *cwbuf = curlx_calloc(1, sizeof(*cwbuf)); if(cwbuf) { cwbuf->type = otype; curlx_dyn_init(&cwbuf->b, DYN_PAUSE_BUFFER); @@ -97,7 +91,7 @@ static void cw_out_buf_free(struct cw_out_buf *cwbuf) { if(cwbuf) { curlx_dyn_free(&cwbuf->b); - free(cwbuf); + curlx_free(cwbuf); } } @@ -252,7 +246,7 @@ static CURLcode cw_out_ptr_flush(struct cw_out_ctx *ctx, size_t wlen, nwritten; CURLcode result; - /* If we errored once, we do not invoke the client callback again */ + /* If we errored once, we do not invoke the client callback again */ if(ctx->errored) return CURLE_WRITE_ERROR; @@ -302,6 +296,7 @@ static CURLcode cw_out_buf_flush(struct cw_out_ctx *ctx, &consumed); if(result && (result != CURLE_AGAIN)) return result; + result = CURLE_OK; if(consumed) { if(consumed == curlx_dyn_len(&cwbuf->b)) { @@ -403,7 +398,7 @@ static CURLcode cw_out_do_write(struct cw_out_ctx *ctx, /* still have buffered data, append and flush */ result = cw_out_append(ctx, data, otype, buf, blen); if(result) - return result; + goto out; result = cw_out_flush_chain(ctx, data, &ctx->buf, flush_all); if(result) goto out; @@ -452,7 +447,7 @@ static CURLcode cw_out_write(struct Curl_easy *data, return result; } - if(type & (CLIENTWRITE_HEADER|CLIENTWRITE_INFO)) { + if(type & (CLIENTWRITE_HEADER | CLIENTWRITE_INFO)) { result = cw_out_do_write(ctx, data, CW_OUT_HDS, flush_all, buf, blen); if(result) return result; diff --git a/lib/cw-out.h b/lib/cw-out.h index 89b9985bb546..fce868d4e44f 100644 --- a/lib/cw-out.h +++ b/lib/cw-out.h @@ -26,7 +26,7 @@ #include "curl_setup.h" -#include "sendf.h" +struct Curl_easy; /** * The client writer type "cw-out" that does the actual writing to diff --git a/lib/cw-pause.c b/lib/cw-pause.c index 1af4e8fa4192..69fd675c3820 100644 --- a/lib/cw-pause.c +++ b/lib/cw-pause.c @@ -24,20 +24,13 @@ #include "curl_setup.h" -#include - #include "urldata.h" #include "bufq.h" #include "cfilters.h" -#include "headers.h" -#include "multiif.h" #include "sendf.h" +#include "curl_trc.h" #include "cw-pause.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - /* body dynbuf sizes */ #define CW_PAUSE_BUF_CHUNK (16 * 1024) @@ -52,12 +45,12 @@ struct cw_pause_buf { static struct cw_pause_buf *cw_pause_buf_create(int type, size_t buflen) { - struct cw_pause_buf *cwbuf = calloc(1, sizeof(*cwbuf)); + struct cw_pause_buf *cwbuf = curlx_calloc(1, sizeof(*cwbuf)); if(cwbuf) { cwbuf->type = type; if(type & CLIENTWRITE_BODY) Curl_bufq_init2(&cwbuf->b, CW_PAUSE_BUF_CHUNK, 1, - (BUFQ_OPT_SOFT_LIMIT|BUFQ_OPT_NO_SPARES)); + (BUFQ_OPT_SOFT_LIMIT | BUFQ_OPT_NO_SPARES)); else Curl_bufq_init(&cwbuf->b, buflen, 1); } @@ -68,7 +61,7 @@ static void cw_pause_buf_free(struct cw_pause_buf *cwbuf) { if(cwbuf) { Curl_bufq_free(&cwbuf->b); - free(cwbuf); + curlx_free(cwbuf); } } diff --git a/lib/cw-pause.h b/lib/cw-pause.h index 2aa1a499cddd..4f436059ce5c 100644 --- a/lib/cw-pause.h +++ b/lib/cw-pause.h @@ -26,7 +26,7 @@ #include "curl_setup.h" -#include "sendf.h" +struct Curl_easy; /** * The client writer type "cw-pause" that buffers writes for @@ -36,5 +36,4 @@ extern const struct Curl_cwtype Curl_cwt_pause; CURLcode Curl_cw_pause_flush(struct Curl_easy *data); - #endif /* HEADER_CURL_CW_PAUSE_H */ diff --git a/lib/dict.c b/lib/dict.c index 3296a45466ad..38d79db0571f 100644 --- a/lib/dict.c +++ b/lib/dict.c @@ -53,22 +53,15 @@ #endif #include "urldata.h" -#include #include "transfer.h" -#include "sendf.h" +#include "curl_trc.h" #include "escape.h" -#include "progress.h" #include "dict.h" -/* The last 2 #include files should be: */ -#include "curl_memory.h" -#include "memdebug.h" - - -#define DICT_MATCH "/MATCH:" -#define DICT_MATCH2 "/M:" -#define DICT_MATCH3 "/FIND:" -#define DICT_DEFINE "/DEFINE:" +#define DICT_MATCH "/MATCH:" +#define DICT_MATCH2 "/M:" +#define DICT_MATCH3 "/FIND:" +#define DICT_DEFINE "/DEFINE:" #define DICT_DEFINE2 "/D:" #define DICT_DEFINE3 "/LOOKUP:" @@ -160,9 +153,9 @@ static CURLcode sendf(struct Curl_easy *data, const char *fmt, ...) if(result) break; - Curl_debug(data, CURLINFO_DATA_OUT, sptr, (size_t)bytes_written); + Curl_debug(data, CURLINFO_DATA_OUT, sptr, bytes_written); - if((size_t)bytes_written != write_len) { + if(bytes_written != write_len) { /* if not all was written at once, we must advance the pointer, decrease the size left and try again! */ write_len -= bytes_written; @@ -172,7 +165,7 @@ static CURLcode sendf(struct Curl_easy *data, const char *fmt, ...) break; } - free(s); /* free the output string */ + curlx_free(s); /* free the output string */ return result; } @@ -197,9 +190,9 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done) if(result) return result; - if(curl_strnequal(path, DICT_MATCH, sizeof(DICT_MATCH)-1) || - curl_strnequal(path, DICT_MATCH2, sizeof(DICT_MATCH2)-1) || - curl_strnequal(path, DICT_MATCH3, sizeof(DICT_MATCH3)-1)) { + if(curl_strnequal(path, DICT_MATCH, sizeof(DICT_MATCH) - 1) || + curl_strnequal(path, DICT_MATCH2, sizeof(DICT_MATCH2) - 1) || + curl_strnequal(path, DICT_MATCH3, sizeof(DICT_MATCH3) - 1)) { word = strchr(path, ':'); if(word) { @@ -244,9 +237,9 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done) } Curl_xfer_setup_recv(data, FIRSTSOCKET, -1); } - else if(curl_strnequal(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) || - curl_strnequal(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) || - curl_strnequal(path, DICT_DEFINE3, sizeof(DICT_DEFINE3)-1)) { + else if(curl_strnequal(path, DICT_DEFINE, sizeof(DICT_DEFINE) - 1) || + curl_strnequal(path, DICT_DEFINE2, sizeof(DICT_DEFINE2) - 1) || + curl_strnequal(path, DICT_DEFINE3, sizeof(DICT_DEFINE3) - 1)) { word = strchr(path, ':'); if(word) { @@ -310,8 +303,8 @@ static CURLcode dict_do(struct Curl_easy *data, bool *done) } error: - free(eword); - free(path); + curlx_free(eword); + curlx_free(path); return result; } #endif /* CURL_DISABLE_DICT */ diff --git a/lib/dllmain.c b/lib/dllmain.c index d871a524847b..7b7d3c7e2e10 100644 --- a/lib/dllmain.c +++ b/lib/dllmain.c @@ -28,16 +28,12 @@ #include #endif -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - /* DllMain() must only be defined for Windows DLL builds. */ #if defined(_WIN32) && !defined(CURL_STATICLIB) #if defined(USE_OPENSSL) && \ !defined(OPENSSL_IS_BORINGSSL) && !defined(OPENSSL_IS_AWSLC) && \ - !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000L + !defined(LIBRESSL_VERSION_NUMBER) #define PREVENT_OPENSSL_MEMLEAK #endif diff --git a/lib/doh.c b/lib/doh.c index 3dd7a2872d2f..d7d25694c809 100644 --- a/lib/doh.c +++ b/lib/doh.c @@ -30,25 +30,19 @@ #include "curl_addrinfo.h" #include "doh.h" -#include "sendf.h" +#include "curl_trc.h" #include "multiif.h" #include "url.h" -#include "share.h" -#include "curlx/base64.h" #include "connect.h" #include "strdup.h" #include "curlx/dynbuf.h" #include "escape.h" #include "urlapi-int.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - #define DNS_CLASS_IN 0x01 #ifndef CURL_DISABLE_VERBOSE_STRINGS -static const char * const errors[]={ +static const char * const errors[] = { "", "Bad label", "Out of range", @@ -79,7 +73,7 @@ static const char *doh_strerror(DOHcode code) UNITTEST DOHcode doh_req_encode(const char *host, DNStype dnstype, unsigned char *dnsp, /* buffer */ - size_t len, /* buffer size */ + size_t len, /* buffer size */ size_t *olen) /* output length */ { const size_t hostlen = strlen(host); @@ -111,7 +105,7 @@ UNITTEST DOHcode doh_req_encode(const char *host, size_t expected_len; DEBUGASSERT(hostlen); expected_len = 12 + 1 + hostlen + 4; - if(host[hostlen-1]!='.') + if(host[hostlen - 1] != '.') expected_len++; if(expected_len > DOH_MAX_DNSREQ_SIZE) @@ -158,9 +152,9 @@ UNITTEST DOHcode doh_req_encode(const char *host, *dnsp++ = 0; /* append zero-length label for root */ - /* There are assigned TYPE codes beyond 255: use range [1..65535] */ + /* There are assigned TYPE codes beyond 255: use range [1..65535] */ *dnsp++ = (unsigned char)(255 & (dnstype >> 8)); /* upper 8 bit TYPE */ - *dnsp++ = (unsigned char)(255 & dnstype); /* lower 8 bit TYPE */ + *dnsp++ = (unsigned char)(255 & dnstype); /* lower 8 bit TYPE */ *dnsp++ = '\0'; /* upper 8 bit CLASS */ *dnsp++ = DNS_CLASS_IN; /* IN - "the Internet" */ @@ -173,8 +167,8 @@ UNITTEST DOHcode doh_req_encode(const char *host, return DOH_OK; } -static size_t -doh_probe_write_cb(char *contents, size_t size, size_t nmemb, void *userp) +static size_t doh_probe_write_cb(char *contents, size_t size, size_t nmemb, + void *userp) { size_t realsize = size * nmemb; struct Curl_easy *data = userp; @@ -269,11 +263,11 @@ static void doh_probe_dtor(void *key, size_t klen, void *e) struct doh_request *doh_req = e; curl_slist_free_all(doh_req->req_hds); curlx_dyn_free(&doh_req->resp_body); - free(e); + curlx_free(e); } } -#define ERROR_CHECK_SETOPT(x,y) \ +#define ERROR_CHECK_SETOPT(x, y) \ do { \ result = curl_easy_setopt((CURL *)doh, x, y); \ if(result && \ @@ -286,7 +280,7 @@ static CURLcode doh_probe_run(struct Curl_easy *data, DNStype dnstype, const char *host, const char *url, CURLM *multi, - unsigned int *pmid) + uint32_t *pmid) { struct Curl_easy *doh = NULL; CURLcode result = CURLE_OK; @@ -294,9 +288,9 @@ static CURLcode doh_probe_run(struct Curl_easy *data, struct doh_request *doh_req; DOHcode d; - *pmid = UINT_MAX; + *pmid = UINT32_MAX; - doh_req = calloc(1, sizeof(*doh_req)); + doh_req = curlx_calloc(1, sizeof(*doh_req)); if(!doh_req) return CURLE_OUT_OF_MEMORY; doh_req->dnstype = dnstype; @@ -311,7 +305,7 @@ static CURLcode doh_probe_run(struct Curl_easy *data, goto error; } - timeout_ms = Curl_timeleft(data, NULL, TRUE); + timeout_ms = Curl_timeleft_ms(data, TRUE); if(timeout_ms <= 0) { result = CURLE_OPERATION_TIMEDOUT; goto error; @@ -350,7 +344,7 @@ static CURLcode doh_probe_run(struct Curl_easy *data, ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTPS); #else /* in debug mode, also allow http */ - ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTP|CURLPROTO_HTTPS); + ERROR_CHECK_SETOPT(CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); #endif ERROR_CHECK_SETOPT(CURLOPT_TIMEOUT_MS, (long)timeout_ms); ERROR_CHECK_SETOPT(CURLOPT_SHARE, (CURLSH *)data->share); @@ -362,11 +356,11 @@ static CURLcode doh_probe_run(struct Curl_easy *data, ERROR_CHECK_SETOPT(CURLOPT_NOSIGNAL, 1L); ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYHOST, - data->set.doh_verifyhost ? 2L : 0L); + data->set.doh_verifyhost ? 2L : 0L); ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYPEER, - data->set.doh_verifypeer ? 1L : 0L); + data->set.doh_verifypeer ? 1L : 0L); ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYSTATUS, - data->set.doh_verifystatus ? 1L : 0L); + data->set.doh_verifystatus ? 1L : 0L); /* Inherit *some* SSL options from the user's transfer. This is a best-guess as to which options are needed for compatibility. #3661 @@ -380,20 +374,16 @@ static CURLcode doh_probe_run(struct Curl_easy *data, doh->set.ssl.custom_capath = data->set.ssl.custom_capath; doh->set.ssl.custom_cablob = data->set.ssl.custom_cablob; if(data->set.str[STRING_SSL_CAFILE]) { - ERROR_CHECK_SETOPT(CURLOPT_CAINFO, - data->set.str[STRING_SSL_CAFILE]); + ERROR_CHECK_SETOPT(CURLOPT_CAINFO, data->set.str[STRING_SSL_CAFILE]); } if(data->set.blobs[BLOB_CAINFO]) { - ERROR_CHECK_SETOPT(CURLOPT_CAINFO_BLOB, - data->set.blobs[BLOB_CAINFO]); + ERROR_CHECK_SETOPT(CURLOPT_CAINFO_BLOB, data->set.blobs[BLOB_CAINFO]); } if(data->set.str[STRING_SSL_CAPATH]) { - ERROR_CHECK_SETOPT(CURLOPT_CAPATH, - data->set.str[STRING_SSL_CAPATH]); + ERROR_CHECK_SETOPT(CURLOPT_CAPATH, data->set.str[STRING_SSL_CAPATH]); } if(data->set.str[STRING_SSL_CRLFILE]) { - ERROR_CHECK_SETOPT(CURLOPT_CRLFILE, - data->set.str[STRING_SSL_CRLFILE]); + ERROR_CHECK_SETOPT(CURLOPT_CRLFILE, data->set.str[STRING_SSL_CRLFILE]); } if(data->set.ssl.certinfo) ERROR_CHECK_SETOPT(CURLOPT_CERTINFO, 1L); @@ -441,15 +431,12 @@ static CURLcode doh_probe_run(struct Curl_easy *data, } /* - * Curl_doh() resolves a name using DoH. It resolves a name and returns a - * 'Curl_addrinfo *' with the address information. + * Curl_doh() starts a name resolve using DoH. It resolves a name and returns + * a 'Curl_addrinfo *' with the address information. */ -struct Curl_addrinfo *Curl_doh(struct Curl_easy *data, - const char *hostname, - int port, - int ip_version, - int *waitp) +CURLcode Curl_doh(struct Curl_easy *data, const char *hostname, + int port, int ip_version) { CURLcode result = CURLE_OK; struct doh_probes *dohp = NULL; @@ -458,23 +445,24 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data, DEBUGASSERT(conn); DEBUGASSERT(!data->state.async.doh); + DEBUGASSERT(hostname && hostname[0]); if(data->state.async.doh) Curl_doh_cleanup(data); data->state.async.done = FALSE; data->state.async.port = port; data->state.async.ip_version = ip_version; - data->state.async.hostname = strdup(hostname); + data->state.async.hostname = curlx_strdup(hostname); if(!data->state.async.hostname) - return NULL; + return CURLE_OUT_OF_MEMORY; /* start clean, consider allocating this struct on demand */ - data->state.async.doh = dohp = calloc(1, sizeof(struct doh_probes)); + data->state.async.doh = dohp = curlx_calloc(1, sizeof(struct doh_probes)); if(!dohp) - return NULL; + return CURLE_OUT_OF_MEMORY; for(i = 0; i < DOH_SLOT_COUNT; ++i) { - dohp->probe_resp[i].probe_mid = UINT_MAX; + dohp->probe_resp[i].probe_mid = UINT32_MAX; curlx_dyn_init(&dohp->probe_resp[i].body, DYN_DOH_RESPONSE); } @@ -520,18 +508,17 @@ struct Curl_addrinfo *Curl_doh(struct Curl_easy *data, qname ? qname : hostname, data->set.str[STRING_DOH], data->multi, &dohp->probe_resp[DOH_SLOT_HTTPS_RR].probe_mid); - free(qname); + curlx_free(qname); if(result) goto error; dohp->pending++; } #endif - *waitp = TRUE; /* this never returns synchronously */ - return NULL; + return CURLE_OK; error: Curl_doh_cleanup(data); - return NULL; + return result; } static DOHcode doh_skipqname(const unsigned char *doh, size_t dohlen, @@ -676,7 +663,7 @@ static DOHcode doh_rdata(const unsigned char *doh, struct dohentry *d) { /* RDATA - - A (TYPE 1): 4 bytes + - A (TYPE 1): 4 bytes - AAAA (TYPE 28): 16 bytes - NS (TYPE 2): N bytes - HTTPS (TYPE 65): N bytes */ @@ -706,7 +693,7 @@ static DOHcode doh_rdata(const unsigned char *doh, return rc; break; case CURL_DNS_TYPE_DNAME: - /* explicit for clarity; just skip; rely on synthesized CNAME */ + /* explicit for clarity; just skip; rely on synthesized CNAME */ break; default: /* unsupported type, just skip it */ @@ -724,7 +711,6 @@ UNITTEST void de_init(struct dohentry *de) curlx_dyn_init(&de->cname[i], DYN_DOH_CNAME); } - UNITTEST DOHcode doh_resp_decode(const unsigned char *doh, size_t dohlen, DNStype dnstype, @@ -858,7 +844,7 @@ UNITTEST DOHcode doh_resp_decode(const unsigned char *doh, #ifdef USE_HTTTPS if((type != CURL_DNS_TYPE_NS) && !d->numcname && !d->numaddr && - !d->numhttps_rrs) + !d->numhttps_rrs) #else if((type != CURL_DNS_TYPE_NS) && !d->numcname && !d->numaddr) #endif @@ -902,8 +888,7 @@ static void doh_show(struct Curl_easy *data, #ifdef USE_HTTPSRR for(i = 0; i < d->numhttps_rrs; i++) { # ifdef DEBUGBUILD - doh_print_buf(data, "DoH HTTPS", - d->https_rrs[i].val, d->https_rrs[i].len); + doh_print_buf(data, "DoH HTTPS", d->https_rrs[i].val, d->https_rrs[i].len); # else infof(data, "DoH HTTPS RR: length %d", d->https_rrs[i].len); # endif @@ -914,7 +899,7 @@ static void doh_show(struct Curl_easy *data, } } #else -#define doh_show(x,y) +#define doh_show(x, y) #endif /* @@ -966,7 +951,7 @@ static CURLcode doh2ai(const struct dohentry *de, const char *hostname, addrtype = AF_INET; } - ai = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + hostlen); + ai = curlx_calloc(1, sizeof(struct Curl_addrinfo) + ss_size + hostlen); if(!ai) { result = CURLE_OUT_OF_MEMORY; break; @@ -1029,16 +1014,16 @@ static CURLcode doh2ai(const struct dohentry *de, const char *hostname, static const char *doh_type2name(DNStype dnstype) { switch(dnstype) { - case CURL_DNS_TYPE_A: - return "A"; - case CURL_DNS_TYPE_AAAA: - return "AAAA"; + case CURL_DNS_TYPE_A: + return "A"; + case CURL_DNS_TYPE_AAAA: + return "AAAA"; #ifdef USE_HTTPSRR - case CURL_DNS_TYPE_HTTPS: - return "HTTPS"; + case CURL_DNS_TYPE_HTTPS: + return "HTTPS"; #endif - default: - return "unknown"; + default: + return "unknown"; } } #endif @@ -1133,7 +1118,7 @@ UNITTEST CURLcode doh_resp_decode_httpsrr(struct Curl_easy *data, *hrr = NULL; if(len <= 2) return CURLE_BAD_FUNCTION_ARGUMENT; - lhrr = calloc(1, sizeof(struct Curl_https_rrinfo)); + lhrr = curlx_calloc(1, sizeof(struct Curl_https_rrinfo)); if(!lhrr) return CURLE_OUT_OF_MEMORY; lhrr->priority = doh_get16bit(cp, 0); @@ -1181,8 +1166,7 @@ UNITTEST void doh_print_httpsrr(struct Curl_easy *data, struct Curl_https_rrinfo *hrr) { DEBUGASSERT(hrr); - infof(data, "HTTPS RR: priority %d, target: %s", - hrr->priority, hrr->target); + infof(data, "HTTPS RR: priority %d, target: %s", hrr->priority, hrr->target); if(hrr->alpns[0] != ALPN_none) infof(data, "HTTPS RR: alpns %u %u %u %u", hrr->alpns[0], hrr->alpns[1], hrr->alpns[2], hrr->alpns[3]); @@ -1218,21 +1202,21 @@ UNITTEST void doh_print_httpsrr(struct Curl_easy *data, CURLcode Curl_doh_is_resolved(struct Curl_easy *data, struct Curl_dns_entry **dnsp) { - CURLcode result; + CURLcode result = CURLE_OK; struct doh_probes *dohp = data->state.async.doh; + struct dohentry de; *dnsp = NULL; /* defaults to no response */ if(!dohp) return CURLE_OUT_OF_MEMORY; - if(dohp->probe_resp[DOH_SLOT_IPV4].probe_mid == UINT_MAX && - dohp->probe_resp[DOH_SLOT_IPV6].probe_mid == UINT_MAX) { + if(dohp->probe_resp[DOH_SLOT_IPV4].probe_mid == UINT32_MAX && + dohp->probe_resp[DOH_SLOT_IPV6].probe_mid == UINT32_MAX) { failf(data, "Could not DoH-resolve: %s", dohp->host); return CONN_IS_PROXIED(data->conn) ? CURLE_COULDNT_RESOLVE_PROXY : CURLE_COULDNT_RESOLVE_HOST; } else if(!dohp->pending) { DOHcode rc[DOH_SLOT_COUNT]; - struct dohentry de; int slot; /* Clear any result the might still be there */ @@ -1264,17 +1248,14 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data, struct Curl_dns_entry *dns; struct Curl_addrinfo *ai; - if(Curl_trc_ft_is_verbose(data, &Curl_trc_feat_dns)) { CURL_TRC_DNS(data, "hostname: %s", dohp->host); doh_show(data, &de); } result = doh2ai(&de, dohp->host, dohp->port, &ai); - if(result) { - de_cleanup(&de); - return result; - } + if(result) + goto error; /* we got a response, create a dns entry. */ dns = Curl_dnscache_mk_entry(data, ai, dohp->host, 0, dohp->port, FALSE); @@ -1287,32 +1268,36 @@ CURLcode Curl_doh_is_resolved(struct Curl_easy *data, de.https_rrs->len, &hrr); if(result) { infof(data, "Failed to decode HTTPS RR"); - return result; + Curl_resolv_unlink(data, &dns); + goto error; } infof(data, "Some HTTPS RR to process"); # ifdef DEBUGBUILD doh_print_httpsrr(data, hrr); # endif dns->hinfo = hrr; - } + } #endif /* and add the entry to the cache */ data->state.async.dns = dns; result = Curl_dnscache_add(data, dns); *dnsp = data->state.async.dns; } + else + Curl_freeaddrinfo(ai); } /* address processing done */ /* All done */ data->state.async.done = TRUE; - de_cleanup(&de); - Curl_doh_cleanup(data); - return result; - } /* !dohp->pending */ + else + /* wait for pending DoH transactions to complete */ + return CURLE_OK; - /* else wait for pending DoH transactions to complete */ - return CURLE_OK; +error: + de_cleanup(&de); + Curl_doh_cleanup(data); + return result; } void Curl_doh_close(struct Curl_easy *data) @@ -1320,17 +1305,16 @@ void Curl_doh_close(struct Curl_easy *data) struct doh_probes *doh = data->state.async.doh; if(doh && data->multi) { struct Curl_easy *probe_data; - unsigned int mid; + uint32_t mid; size_t slot; for(slot = 0; slot < DOH_SLOT_COUNT; slot++) { mid = doh->probe_resp[slot].probe_mid; - if(mid == UINT_MAX) + if(mid == UINT32_MAX) continue; - doh->probe_resp[slot].probe_mid = UINT_MAX; + doh->probe_resp[slot].probe_mid = UINT32_MAX; /* should have been called before data is removed from multi handle */ DEBUGASSERT(data->multi); - probe_data = data->multi ? Curl_multi_get_easy(data->multi, mid) : - NULL; + probe_data = data->multi ? Curl_multi_get_easy(data->multi, mid) : NULL; if(!probe_data) { DEBUGF(infof(data, "Curl_doh_close: xfer for mid=%u not found!", doh->probe_resp[slot].probe_mid)); diff --git a/lib/doh.h b/lib/doh.h index 3fd7de2c1c57..16732173ab67 100644 --- a/lib/doh.h +++ b/lib/doh.h @@ -96,7 +96,7 @@ struct doh_request { }; struct doh_response { - unsigned int probe_mid; + uint32_t probe_mid; struct dynbuf body; DNStype dnstype; CURLcode result; @@ -112,20 +112,17 @@ struct doh_probes { }; /* - * Curl_doh() resolve a name using DoH (DNS-over-HTTPS). It resolves a name - * and returns a 'Curl_addrinfo *' with the address information. + * Curl_doh() starts a name resolve using DoH (DNS-over-HTTPS). It resolves a + * name and returns a 'Curl_addrinfo *' with the address information. */ -struct Curl_addrinfo *Curl_doh(struct Curl_easy *data, - const char *hostname, - int port, - int ip_version, - int *waitp); +CURLcode Curl_doh(struct Curl_easy *data, const char *hostname, + int port, int ip_version); CURLcode Curl_doh_is_resolved(struct Curl_easy *data, struct Curl_dns_entry **dns); -#define DOH_MAX_ADDR 24 +#define DOH_MAX_ADDR 24 #define DOH_MAX_CNAME 4 #define DOH_MAX_HTTPS 4 @@ -183,8 +180,8 @@ UNITTEST void de_cleanup(struct dohentry *d); #endif #else /* if DoH is disabled */ -#define Curl_doh(a,b,c,d,e) NULL -#define Curl_doh_is_resolved(x,y) CURLE_COULDNT_RESOLVE_HOST +#define Curl_doh(a, b, c, d, e) NULL +#define Curl_doh_is_resolved(x, y) CURLE_COULDNT_RESOLVE_HOST #endif #endif /* HEADER_CURL_DOH_H */ diff --git a/lib/dynhds.c b/lib/dynhds.c index 95d415bf0b49..d0a3eb6a74c4 100644 --- a/lib/dynhds.c +++ b/lib/dynhds.c @@ -23,6 +23,7 @@ ***************************************************************************/ #include "curl_setup.h" + #include "dynhds.h" #include "strcase.h" @@ -31,10 +32,6 @@ #include #endif /* USE_NGHTTP2 */ -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - static struct dynhds_entry * entry_new(const char *name, size_t namelen, @@ -45,7 +42,7 @@ entry_new(const char *name, size_t namelen, DEBUGASSERT(name); DEBUGASSERT(value); - e = calloc(1, sizeof(*e) + namelen + valuelen + 2); + e = curlx_calloc(1, sizeof(*e) + namelen + valuelen + 2); if(!e) return NULL; e->name = p = ((char *)e) + sizeof(*e); @@ -59,16 +56,15 @@ entry_new(const char *name, size_t namelen, return e; } -static struct dynhds_entry * -entry_append(struct dynhds_entry *e, - const char *value, size_t valuelen) +static struct dynhds_entry *entry_append(struct dynhds_entry *e, + const char *value, size_t valuelen) { struct dynhds_entry *e2; size_t valuelen2 = e->valuelen + 1 + valuelen; char *p; DEBUGASSERT(value); - e2 = calloc(1, sizeof(*e) + e->namelen + valuelen2 + 2); + e2 = curlx_calloc(1, sizeof(*e) + e->namelen + valuelen2 + 2); if(!e2) return NULL; e2->name = p = ((char *)e2) + sizeof(*e2); @@ -85,7 +81,7 @@ entry_append(struct dynhds_entry *e, static void entry_free(struct dynhds_entry *e) { - free(e); + curlx_free(e); } void Curl_dynhds_init(struct dynhds *dynhds, size_t max_entries, @@ -175,7 +171,7 @@ CURLcode Curl_dynhds_add(struct dynhds *dynhds, if(dynhds->strs_len + namelen + valuelen > dynhds->max_strs_size) return CURLE_OUT_OF_MEMORY; -entry = entry_new(name, namelen, value, valuelen, dynhds->opts); + entry = entry_new(name, namelen, value, valuelen, dynhds->opts); if(!entry) goto out; @@ -186,7 +182,7 @@ entry = entry_new(name, namelen, value, valuelen, dynhds->opts); if(dynhds->max_entries && nallc > dynhds->max_entries) nallc = dynhds->max_entries; - nhds = calloc(nallc, sizeof(struct dynhds_entry *)); + nhds = curlx_calloc(nallc, sizeof(struct dynhds_entry *)); if(!nhds) goto out; if(dynhds->hds) { @@ -238,11 +234,11 @@ CURLcode Curl_dynhds_h1_add_line(struct dynhds *dynhds, } if(!line_len) return CURLE_BAD_FUNCTION_ARGUMENT; - e = dynhds->hds[dynhds->hds_len-1]; + e = dynhds->hds[dynhds->hds_len - 1]; e2 = entry_append(e, line, line_len); if(!e2) return CURLE_OUT_OF_MEMORY; - dynhds->hds[dynhds->hds_len-1] = e2; + dynhds->hds[dynhds->hds_len - 1] = e2; entry_free(e); return CURLE_OK; } @@ -374,7 +370,7 @@ CURLcode Curl_dynhds_h1_dprint(struct dynhds *dynhds, struct dynbuf *dbuf) nghttp2_nv *Curl_dynhds_to_nva(struct dynhds *dynhds, size_t *pcount) { - nghttp2_nv *nva = calloc(1, sizeof(nghttp2_nv) * dynhds->hds_len); + nghttp2_nv *nva = curlx_calloc(1, sizeof(nghttp2_nv) * dynhds->hds_len); size_t i; *pcount = 0; diff --git a/lib/dynhds.h b/lib/dynhds.h index e533dcc3699e..170721cf78c5 100644 --- a/lib/dynhds.h +++ b/lib/dynhds.h @@ -25,7 +25,6 @@ ***************************************************************************/ #include "curl_setup.h" -#include #include "curlx/dynbuf.h" struct dynbuf; @@ -126,7 +125,6 @@ size_t Curl_dynhds_remove(struct dynhds *dynhds, const char *name, size_t namelen); size_t Curl_dynhds_cremove(struct dynhds *dynhds, const char *name); - /** * Set the give header name and value, replacing any entries with * the same name. The header is added at the end of all (remaining) diff --git a/lib/easy.c b/lib/easy.c index 793a18f33eb8..8926422780f4 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -45,7 +45,6 @@ #endif #include "urldata.h" -#include #include "transfer.h" #include "vtls/vtls.h" #include "vtls/vtls_scache.h" @@ -53,20 +52,19 @@ #include "url.h" #include "getinfo.h" #include "hostip.h" -#include "share.h" #include "strdup.h" -#include "progress.h" #include "easyif.h" #include "multiif.h" +#include "multi_ev.h" #include "select.h" #include "cfilters.h" -#include "sendf.h" /* for failf function prototype */ +#include "sendf.h" +#include "curl_trc.h" #include "connect.h" /* for Curl_getconnectinfo */ #include "slist.h" #include "mime.h" #include "amigaos.h" #include "macos.h" -#include "curlx/warnless.h" #include "curlx/wait.h" #include "sigpipe.h" #include "vssh/ssh.h" @@ -75,15 +73,12 @@ #include "system_win32.h" #include "http2.h" #include "curlx/dynbuf.h" +#include "bufref.h" #include "altsvc.h" #include "hsts.h" #include "easy_lock.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - /* true globals -- for curl_global_init() and curl_global_cleanup() */ static unsigned int initialized; static long easy_init_flags; @@ -91,7 +86,7 @@ static long easy_init_flags; #ifdef GLOBAL_INIT_IS_THREADSAFE static curl_simple_lock s_lock = CURL_SIMPLE_LOCK_INIT; -#define global_init_lock() curl_simple_lock_lock(&s_lock) +#define global_init_lock() curl_simple_lock_lock(&s_lock) #define global_init_unlock() curl_simple_lock_unlock(&s_lock) #else @@ -106,13 +101,15 @@ static curl_simple_lock s_lock = CURL_SIMPLE_LOCK_INIT; * ways, but at this point it must be defined as the system-supplied strdup * so the callback pointer is initialized correctly. */ -#ifdef UNDER_CE +#ifdef HAVE_STRDUP +#ifdef _WIN32 #define system_strdup _strdup -#elif !defined(HAVE_STRDUP) -#define system_strdup Curl_strdup #else #define system_strdup strdup #endif +#else +#define system_strdup Curl_strdup +#endif #if defined(_MSC_VER) && defined(_DLL) # pragma warning(push) @@ -200,7 +197,7 @@ static CURLcode global_init(long flags, bool memoryfuncs) #ifdef DEBUGBUILD if(getenv("CURL_GLOBAL_INIT")) /* alloc data that will leak if *cleanup() is not called! */ - leakpointer = malloc(1); + leakpointer = curlx_malloc(1); #endif return CURLE_OK; @@ -210,7 +207,6 @@ static CURLcode global_init(long flags, bool memoryfuncs) return CURLE_FAILED_INIT; } - /** * curl_global_init() globally initializes curl given a bitwise set of the * different features of what to initialize. @@ -299,7 +295,7 @@ void curl_global_cleanup(void) Curl_ssh_cleanup(); #ifdef DEBUGBUILD - free(leakpointer); + curlx_free(leakpointer); #endif easy_init_flags = 0; @@ -413,7 +409,6 @@ static int events_timer(CURLM *multi, /* multi handle */ return 0; } - /* poll2cselect * * convert from poll() bit definitions to libcurl's CURL_CSELECT_* ones @@ -430,7 +425,6 @@ static int poll2cselect(int pollmask) return omask; } - /* socketcb2poll * * convert from libcurl' CURL_POLL_* bit definitions to poll()'s @@ -480,17 +474,16 @@ static int events_socket(CURL *easy, /* easy handle */ prev->next = nxt; else ev->list = nxt; - free(m); + curlx_free(m); infof(data, "socket cb: socket %" FMT_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(data, "socket cb: socket %" FMT_SOCKET_T - " UPDATED as %s%s", s, - (what&CURL_POLL_IN) ? "IN" : "", - (what&CURL_POLL_OUT) ? "OUT" : ""); + infof(data, "socket cb: socket %" FMT_SOCKET_T " UPDATED as %s%s", s, + (what & CURL_POLL_IN) ? "IN" : "", + (what & CURL_POLL_OUT) ? "OUT" : ""); } break; } @@ -506,7 +499,7 @@ static int events_socket(CURL *easy, /* easy handle */ DEBUGASSERT(0); } else { - m = malloc(sizeof(struct socketmonitor)); + m = curlx_malloc(sizeof(struct socketmonitor)); if(m) { m->next = ev->list; m->socket.fd = s; @@ -514,8 +507,8 @@ static int events_socket(CURL *easy, /* easy handle */ m->socket.revents = 0; ev->list = m; infof(data, "socket cb: socket %" FMT_SOCKET_T " ADDED as %s%s", s, - (what&CURL_POLL_IN) ? "IN" : "", - (what&CURL_POLL_OUT) ? "OUT" : ""); + (what & CURL_POLL_IN) ? "IN" : "", + (what & CURL_POLL_OUT) ? "OUT" : ""); } else return CURLE_OUT_OF_MEMORY; @@ -525,7 +518,6 @@ static int events_socket(CURL *easy, /* easy handle */ return 0; } - /* * events_setup() * @@ -606,18 +598,18 @@ static CURLcode poll_fds(struct events *ev, static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev) { bool done = FALSE; - CURLMcode mcode = CURLM_OK; + CURLMcode mresult = CURLM_OK; CURLcode result = CURLE_OK; while(!done) { CURLMsg *msg; struct pollfd fds[4]; int pollrc; - struct curltime before; + struct curltime start; const unsigned int numfds = populate_fds(fds, ev); /* get the time stamp to use to figure out how long poll takes */ - before = curlx_now(); + curlx_pnow(&start); result = poll_fds(ev, fds, numfds, &pollrc); if(result) @@ -629,8 +621,8 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev) /* timeout! */ ev->ms = 0; /* curl_mfprintf(stderr, "call curl_multi_socket_action(TIMEOUT)\n"); */ - mcode = curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0, - &ev->running_handles); + mresult = curl_multi_socket_action(multi, CURL_SOCKET_TIMEOUT, 0, + &ev->running_handles); } else { /* here pollrc is > 0 */ @@ -644,31 +636,30 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev) /* sending infof "randomly" to the first easy handle */ infof(multi->admin, "call curl_multi_socket_action(socket " "%" FMT_SOCKET_T ")", (curl_socket_t)fds[i].fd); - mcode = curl_multi_socket_action(multi, fds[i].fd, act, - &ev->running_handles); + mresult = curl_multi_socket_action(multi, fds[i].fd, act, + &ev->running_handles); } } - if(!ev->msbump && ev->ms >= 0) { /* If nothing updated the timeout, we decrease it by the spent time. * If it was updated, it has the new timeout time stored already. */ - timediff_t timediff = curlx_timediff(curlx_now(), before); - if(timediff > 0) { + timediff_t spent_ms = curlx_timediff_ms(curlx_now(), start); + if(spent_ms > 0) { #if DEBUG_EV_POLL curl_mfprintf(stderr, "poll timeout %ldms not updated, decrease by " - "time spent %ldms\n", ev->ms, (long)timediff); + "time spent %ldms\n", ev->ms, (long)spent_ms); #endif - if(timediff > ev->ms) + if(spent_ms > ev->ms) ev->ms = 0; else - ev->ms -= (long)timediff; + ev->ms -= (long)spent_ms; } } } - if(mcode) + if(mresult) return CURLE_URL_MALFORMAT; /* we do not really care about the "msgs_in_queue" value returned in the @@ -683,7 +674,6 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev) return result; } - /* easy_events() * * Runs a transfer in a blocking manner using the events-based API @@ -692,7 +682,7 @@ static CURLcode easy_events(struct Curl_multi *multi) { /* this struct is made static to allow it to be used after this function returns and curl_multi_remove_handle() is called */ - static struct events evs = {-1, FALSE, 0, NULL, 0}; + static struct events evs = { -1, FALSE, 0, NULL, 0 }; /* if running event-based, do some further multi inits */ events_setup(multi, &evs); @@ -707,19 +697,19 @@ static CURLcode easy_events(struct Curl_multi *multi) static CURLcode easy_transfer(struct Curl_multi *multi) { bool done = FALSE; - CURLMcode mcode = CURLM_OK; + CURLMcode mresult = CURLM_OK; CURLcode result = CURLE_OK; - while(!done && !mcode) { + while(!done && !mresult) { int still_running = 0; - mcode = curl_multi_poll(multi, NULL, 0, 1000, NULL); + mresult = curl_multi_poll(multi, NULL, 0, 1000, NULL); - if(!mcode) - mcode = curl_multi_perform(multi, &still_running); + if(!mresult) + mresult = curl_multi_perform(multi, &still_running); /* only read 'still_running' if curl_multi_perform() return OK */ - if(!mcode && !still_running) { + if(!mresult && !still_running) { int rc; CURLMsg *msg = curl_multi_info_read(multi, &rc); if(msg) { @@ -730,8 +720,8 @@ 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 : + if(mresult) { + result = (mresult == CURLM_OUT_OF_MEMORY) ? CURLE_OUT_OF_MEMORY : /* The other multi errors should never happen, so return something suitably generic */ CURLE_BAD_FUNCTION_ARGUMENT; @@ -740,7 +730,6 @@ static CURLcode easy_transfer(struct Curl_multi *multi) return result; } - /* * easy_perform() is the internal interface that performs a blocking * transfer as previously setup. @@ -761,7 +750,7 @@ static CURLcode easy_transfer(struct Curl_multi *multi) static CURLcode easy_perform(struct Curl_easy *data, bool events) { struct Curl_multi *multi; - CURLMcode mcode; + CURLMcode mresult; CURLcode result = CURLE_OK; SIGPIPE_VARIABLE(pipe_st); @@ -809,10 +798,10 @@ static CURLcode easy_perform(struct Curl_easy *data, bool events) curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, (long)data->set.maxconnects); data->multi_easy = NULL; /* pretend it does not exist */ - mcode = curl_multi_add_handle(multi, data); - if(mcode) { + mresult = curl_multi_add_handle(multi, data); + if(mresult) { curl_multi_cleanup(multi); - if(mcode == CURLM_OUT_OF_MEMORY) + if(mresult == CURLM_OUT_OF_MEMORY) return CURLE_OUT_OF_MEMORY; return CURLE_FAILED_INIT; } @@ -929,7 +918,7 @@ static CURLcode dupset(struct Curl_easy *dst, struct Curl_easy *src) i = STRING_COPYPOSTFIELDS; if(src->set.str[i]) { if(src->set.postfieldsize == -1) - dst->set.str[i] = strdup(src->set.str[i]); + dst->set.str[i] = curlx_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], @@ -970,7 +959,7 @@ CURL *curl_easy_duphandle(CURL *d) if(!GOOD_EASY_HANDLE(data)) goto fail; - outcurl = calloc(1, sizeof(struct Curl_easy)); + outcurl = curlx_calloc(1, sizeof(struct Curl_easy)); if(!outcurl) goto fail; @@ -984,14 +973,16 @@ CURL *curl_easy_duphandle(CURL *d) Curl_hash_init(&outcurl->meta_hash, 23, Curl_hash_str, curlx_str_key_compare, dupeasy_meta_freeentry); curlx_dyn_init(&outcurl->state.headerb, CURL_MAX_HTTP_HEADER); + Curl_bufref_init(&outcurl->state.url); + Curl_bufref_init(&outcurl->state.referer); Curl_netrc_init(&outcurl->state.netrc); /* the connection pool is setup on demand */ outcurl->state.lastconnect_id = -1; outcurl->state.recent_conn_id = -1; outcurl->id = -1; - outcurl->mid = UINT_MAX; - outcurl->master_mid = UINT_MAX; + outcurl->mid = UINT32_MAX; + outcurl->master_mid = UINT32_MAX; #ifndef CURL_DISABLE_HTTP Curl_llist_init(&outcurl->state.httphdrs, NULL); @@ -1010,10 +1001,10 @@ CURL *curl_easy_duphandle(CURL *d) 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(outcurl, NULL, outcurl->cookies, - data->set.cookiesession); + outcurl->cookies = Curl_cookie_init(); if(!outcurl->cookies) goto fail; + outcurl->state.cookie_engine = TRUE; } if(data->state.cookielist) { @@ -1023,18 +1014,19 @@ CURL *curl_easy_duphandle(CURL *d) } #endif - if(data->state.url) { - outcurl->state.url = strdup(data->state.url); - if(!outcurl->state.url) + if(Curl_bufref_ptr(&data->state.url)) { + Curl_bufref_set(&outcurl->state.url, + Curl_bufref_dup(&data->state.url), 0, + curl_free); + if(!Curl_bufref_ptr(&outcurl->state.url)) goto fail; - outcurl->state.url_alloc = TRUE; } - - if(data->state.referer) { - outcurl->state.referer = strdup(data->state.referer); - if(!outcurl->state.referer) + if(Curl_bufref_ptr(&data->state.referer)) { + Curl_bufref_set(&outcurl->state.referer, + Curl_bufref_dup(&data->state.referer), 0, + curl_free); + if(!Curl_bufref_ptr(&outcurl->state.referer)) goto fail; - outcurl->state.referer_alloc = TRUE; } /* Reinitialize an SSL engine for the new handle @@ -1075,13 +1067,13 @@ CURL *curl_easy_duphandle(CURL *d) if(outcurl) { #ifndef CURL_DISABLE_COOKIES - free(outcurl->cookies); + curlx_free(outcurl->cookies); #endif curlx_dyn_free(&outcurl->state.headerb); Curl_altsvc_cleanup(&outcurl->asi); Curl_hsts_cleanup(&outcurl->hsts); Curl_freeset(outcurl); - free(outcurl); + curlx_free(outcurl); } return NULL; @@ -1128,7 +1120,7 @@ void curl_easy_reset(CURL *d) #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_DIGEST_AUTH) Curl_http_auth_cleanup_digest(data); #endif - data->master_mid = UINT_MAX; + data->master_mid = UINT32_MAX; } /* @@ -1165,7 +1157,8 @@ CURLcode curl_easy_pause(CURL *d, int action) send_paused = Curl_xfer_send_is_paused(data); send_paused_new = (action & CURLPAUSE_SEND); - if(send_paused != send_paused_new) { + if((send_paused != send_paused_new) || + (send_paused_new != Curl_creader_is_paused(data))) { changed = TRUE; result = Curl_1st_err(result, Curl_xfer_pause_send(data, send_paused_new)); } @@ -1202,7 +1195,6 @@ CURLcode curl_easy_pause(CURL *d, int action) return result; } - static CURLcode easy_connection(struct Curl_easy *data, struct connectdata **connp) { diff --git a/lib/easy_lock.h b/lib/easy_lock.h index f8998cc5472c..927b11d70f72 100644 --- a/lib/easy_lock.h +++ b/lib/easy_lock.h @@ -30,10 +30,10 @@ #if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600 -#define curl_simple_lock SRWLOCK +#define curl_simple_lock SRWLOCK #define CURL_SIMPLE_LOCK_INIT SRWLOCK_INIT -#define curl_simple_lock_lock(m) AcquireSRWLockExclusive(m) +#define curl_simple_lock_lock(m) AcquireSRWLockExclusive(m) #define curl_simple_lock_unlock(m) ReleaseSRWLockExclusive(m) #elif defined(HAVE_ATOMIC) && defined(HAVE_STDATOMIC_H) @@ -42,7 +42,7 @@ #include #endif -#define curl_simple_lock atomic_int +#define curl_simple_lock atomic_int #define CURL_SIMPLE_LOCK_INIT 0 #ifndef __INTEL_COMPILER @@ -59,7 +59,7 @@ #endif #endif -#endif +#endif /* !__INTEL_COMPILER */ static CURL_INLINE void curl_simple_lock_lock(curl_simple_lock *lock) { @@ -91,14 +91,14 @@ static CURL_INLINE void curl_simple_lock_unlock(curl_simple_lock *lock) #include -#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 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 +#undef GLOBAL_INIT_IS_THREADSAFE #endif diff --git a/lib/easygetopt.c b/lib/easygetopt.c index 7ac39bc634e8..8eb96ebd1719 100644 --- a/lib/easygetopt.c +++ b/lib/easygetopt.c @@ -23,6 +23,7 @@ ***************************************************************************/ #include "curl_setup.h" + #include "easyoptions.h" #ifndef CURL_DISABLE_GETOPTIONS diff --git a/lib/easyoptions.c b/lib/easyoptions.c index 03d676df0e73..4c0b4f0ce4ad 100644 --- a/lib/easyoptions.c +++ b/lib/easyoptions.c @@ -25,352 +25,357 @@ /* This source code is generated by optiontable.pl - DO NOT EDIT BY HAND */ #include "curl_setup.h" + #include "easyoptions.h" /* all easy setopt options listed in alphabetical order */ const struct curl_easyoption Curl_easyopts[] = { - {"ABSTRACT_UNIX_SOCKET", CURLOPT_ABSTRACT_UNIX_SOCKET, CURLOT_STRING, 0}, - {"ACCEPTTIMEOUT_MS", CURLOPT_ACCEPTTIMEOUT_MS, CURLOT_LONG, 0}, - {"ACCEPT_ENCODING", CURLOPT_ACCEPT_ENCODING, CURLOT_STRING, 0}, - {"ADDRESS_SCOPE", CURLOPT_ADDRESS_SCOPE, CURLOT_LONG, 0}, - {"ALTSVC", CURLOPT_ALTSVC, CURLOT_STRING, 0}, - {"ALTSVC_CTRL", CURLOPT_ALTSVC_CTRL, CURLOT_LONG, 0}, - {"APPEND", CURLOPT_APPEND, CURLOT_LONG, 0}, - {"AUTOREFERER", CURLOPT_AUTOREFERER, CURLOT_LONG, 0}, - {"AWS_SIGV4", CURLOPT_AWS_SIGV4, CURLOT_STRING, 0}, - {"BUFFERSIZE", CURLOPT_BUFFERSIZE, CURLOT_LONG, 0}, - {"CAINFO", CURLOPT_CAINFO, CURLOT_STRING, 0}, - {"CAINFO_BLOB", CURLOPT_CAINFO_BLOB, CURLOT_BLOB, 0}, - {"CAPATH", CURLOPT_CAPATH, CURLOT_STRING, 0}, - {"CA_CACHE_TIMEOUT", CURLOPT_CA_CACHE_TIMEOUT, CURLOT_LONG, 0}, - {"CERTINFO", CURLOPT_CERTINFO, CURLOT_LONG, 0}, - {"CHUNK_BGN_FUNCTION", CURLOPT_CHUNK_BGN_FUNCTION, CURLOT_FUNCTION, 0}, - {"CHUNK_DATA", CURLOPT_CHUNK_DATA, CURLOT_CBPTR, 0}, - {"CHUNK_END_FUNCTION", CURLOPT_CHUNK_END_FUNCTION, CURLOT_FUNCTION, 0}, - {"CLOSESOCKETDATA", CURLOPT_CLOSESOCKETDATA, CURLOT_CBPTR, 0}, - {"CLOSESOCKETFUNCTION", CURLOPT_CLOSESOCKETFUNCTION, CURLOT_FUNCTION, 0}, - {"CONNECTTIMEOUT", CURLOPT_CONNECTTIMEOUT, CURLOT_LONG, 0}, - {"CONNECTTIMEOUT_MS", CURLOPT_CONNECTTIMEOUT_MS, CURLOT_LONG, 0}, - {"CONNECT_ONLY", CURLOPT_CONNECT_ONLY, CURLOT_LONG, 0}, - {"CONNECT_TO", CURLOPT_CONNECT_TO, CURLOT_SLIST, 0}, - {"CONV_FROM_NETWORK_FUNCTION", CURLOPT_CONV_FROM_NETWORK_FUNCTION, - CURLOT_FUNCTION, 0}, - {"CONV_FROM_UTF8_FUNCTION", CURLOPT_CONV_FROM_UTF8_FUNCTION, - CURLOT_FUNCTION, 0}, - {"CONV_TO_NETWORK_FUNCTION", CURLOPT_CONV_TO_NETWORK_FUNCTION, - CURLOT_FUNCTION, 0}, - {"COOKIE", CURLOPT_COOKIE, CURLOT_STRING, 0}, - {"COOKIEFILE", CURLOPT_COOKIEFILE, CURLOT_STRING, 0}, - {"COOKIEJAR", CURLOPT_COOKIEJAR, CURLOT_STRING, 0}, - {"COOKIELIST", CURLOPT_COOKIELIST, CURLOT_STRING, 0}, - {"COOKIESESSION", CURLOPT_COOKIESESSION, CURLOT_LONG, 0}, - {"COPYPOSTFIELDS", CURLOPT_COPYPOSTFIELDS, CURLOT_OBJECT, 0}, - {"CRLF", CURLOPT_CRLF, CURLOT_LONG, 0}, - {"CRLFILE", CURLOPT_CRLFILE, CURLOT_STRING, 0}, - {"CURLU", CURLOPT_CURLU, CURLOT_OBJECT, 0}, - {"CUSTOMREQUEST", CURLOPT_CUSTOMREQUEST, CURLOT_STRING, 0}, - {"DEBUGDATA", CURLOPT_DEBUGDATA, CURLOT_CBPTR, 0}, - {"DEBUGFUNCTION", CURLOPT_DEBUGFUNCTION, CURLOT_FUNCTION, 0}, - {"DEFAULT_PROTOCOL", CURLOPT_DEFAULT_PROTOCOL, CURLOT_STRING, 0}, - {"DIRLISTONLY", CURLOPT_DIRLISTONLY, CURLOT_LONG, 0}, - {"DISALLOW_USERNAME_IN_URL", CURLOPT_DISALLOW_USERNAME_IN_URL, - CURLOT_LONG, 0}, - {"DNS_CACHE_TIMEOUT", CURLOPT_DNS_CACHE_TIMEOUT, CURLOT_LONG, 0}, - {"DNS_INTERFACE", CURLOPT_DNS_INTERFACE, CURLOT_STRING, 0}, - {"DNS_LOCAL_IP4", CURLOPT_DNS_LOCAL_IP4, CURLOT_STRING, 0}, - {"DNS_LOCAL_IP6", CURLOPT_DNS_LOCAL_IP6, CURLOT_STRING, 0}, - {"DNS_SERVERS", CURLOPT_DNS_SERVERS, CURLOT_STRING, 0}, - {"DNS_SHUFFLE_ADDRESSES", CURLOPT_DNS_SHUFFLE_ADDRESSES, CURLOT_LONG, 0}, - {"DNS_USE_GLOBAL_CACHE", CURLOPT_DNS_USE_GLOBAL_CACHE, CURLOT_LONG, 0}, - {"DOH_SSL_VERIFYHOST", CURLOPT_DOH_SSL_VERIFYHOST, CURLOT_LONG, 0}, - {"DOH_SSL_VERIFYPEER", CURLOPT_DOH_SSL_VERIFYPEER, CURLOT_LONG, 0}, - {"DOH_SSL_VERIFYSTATUS", CURLOPT_DOH_SSL_VERIFYSTATUS, CURLOT_LONG, 0}, - {"DOH_URL", CURLOPT_DOH_URL, CURLOT_STRING, 0}, - {"ECH", CURLOPT_ECH, CURLOT_STRING, 0}, - {"EGDSOCKET", CURLOPT_EGDSOCKET, CURLOT_STRING, 0}, - {"ENCODING", CURLOPT_ACCEPT_ENCODING, CURLOT_STRING, CURLOT_FLAG_ALIAS}, - {"ERRORBUFFER", CURLOPT_ERRORBUFFER, CURLOT_OBJECT, 0}, - {"EXPECT_100_TIMEOUT_MS", CURLOPT_EXPECT_100_TIMEOUT_MS, CURLOT_LONG, 0}, - {"FAILONERROR", CURLOPT_FAILONERROR, CURLOT_LONG, 0}, - {"FILE", CURLOPT_WRITEDATA, CURLOT_CBPTR, CURLOT_FLAG_ALIAS}, - {"FILETIME", CURLOPT_FILETIME, CURLOT_LONG, 0}, - {"FNMATCH_DATA", CURLOPT_FNMATCH_DATA, CURLOT_CBPTR, 0}, - {"FNMATCH_FUNCTION", CURLOPT_FNMATCH_FUNCTION, CURLOT_FUNCTION, 0}, - {"FOLLOWLOCATION", CURLOPT_FOLLOWLOCATION, CURLOT_LONG, 0}, - {"FORBID_REUSE", CURLOPT_FORBID_REUSE, CURLOT_LONG, 0}, - {"FRESH_CONNECT", CURLOPT_FRESH_CONNECT, CURLOT_LONG, 0}, - {"FTPAPPEND", CURLOPT_APPEND, CURLOT_LONG, CURLOT_FLAG_ALIAS}, - {"FTPLISTONLY", CURLOPT_DIRLISTONLY, CURLOT_LONG, CURLOT_FLAG_ALIAS}, - {"FTPPORT", CURLOPT_FTPPORT, CURLOT_STRING, 0}, - {"FTPSSLAUTH", CURLOPT_FTPSSLAUTH, CURLOT_VALUES, 0}, - {"FTP_ACCOUNT", CURLOPT_FTP_ACCOUNT, CURLOT_STRING, 0}, - {"FTP_ALTERNATIVE_TO_USER", CURLOPT_FTP_ALTERNATIVE_TO_USER, - CURLOT_STRING, 0}, - {"FTP_CREATE_MISSING_DIRS", CURLOPT_FTP_CREATE_MISSING_DIRS, - CURLOT_LONG, 0}, - {"FTP_FILEMETHOD", CURLOPT_FTP_FILEMETHOD, CURLOT_VALUES, 0}, - {"FTP_RESPONSE_TIMEOUT", CURLOPT_SERVER_RESPONSE_TIMEOUT, - CURLOT_LONG, CURLOT_FLAG_ALIAS}, - {"FTP_SKIP_PASV_IP", CURLOPT_FTP_SKIP_PASV_IP, CURLOT_LONG, 0}, - {"FTP_SSL", CURLOPT_USE_SSL, CURLOT_VALUES, CURLOT_FLAG_ALIAS}, - {"FTP_SSL_CCC", CURLOPT_FTP_SSL_CCC, CURLOT_LONG, 0}, - {"FTP_USE_EPRT", CURLOPT_FTP_USE_EPRT, CURLOT_LONG, 0}, - {"FTP_USE_EPSV", CURLOPT_FTP_USE_EPSV, CURLOT_LONG, 0}, - {"FTP_USE_PRET", CURLOPT_FTP_USE_PRET, CURLOT_LONG, 0}, - {"GSSAPI_DELEGATION", CURLOPT_GSSAPI_DELEGATION, CURLOT_VALUES, 0}, - {"HAPPY_EYEBALLS_TIMEOUT_MS", CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS, - CURLOT_LONG, 0}, - {"HAPROXYPROTOCOL", CURLOPT_HAPROXYPROTOCOL, CURLOT_LONG, 0}, - {"HAPROXY_CLIENT_IP", CURLOPT_HAPROXY_CLIENT_IP, CURLOT_STRING, 0}, - {"HEADER", CURLOPT_HEADER, CURLOT_LONG, 0}, - {"HEADERDATA", CURLOPT_HEADERDATA, CURLOT_CBPTR, 0}, - {"HEADERFUNCTION", CURLOPT_HEADERFUNCTION, CURLOT_FUNCTION, 0}, - {"HEADEROPT", CURLOPT_HEADEROPT, CURLOT_VALUES, 0}, - {"HSTS", CURLOPT_HSTS, CURLOT_STRING, 0}, - {"HSTSREADDATA", CURLOPT_HSTSREADDATA, CURLOT_CBPTR, 0}, - {"HSTSREADFUNCTION", CURLOPT_HSTSREADFUNCTION, CURLOT_FUNCTION, 0}, - {"HSTSWRITEDATA", CURLOPT_HSTSWRITEDATA, CURLOT_CBPTR, 0}, - {"HSTSWRITEFUNCTION", CURLOPT_HSTSWRITEFUNCTION, CURLOT_FUNCTION, 0}, - {"HSTS_CTRL", CURLOPT_HSTS_CTRL, CURLOT_LONG, 0}, - {"HTTP09_ALLOWED", CURLOPT_HTTP09_ALLOWED, CURLOT_LONG, 0}, - {"HTTP200ALIASES", CURLOPT_HTTP200ALIASES, CURLOT_SLIST, 0}, - {"HTTPAUTH", CURLOPT_HTTPAUTH, CURLOT_VALUES, 0}, - {"HTTPGET", CURLOPT_HTTPGET, CURLOT_LONG, 0}, - {"HTTPHEADER", CURLOPT_HTTPHEADER, CURLOT_SLIST, 0}, - {"HTTPPOST", CURLOPT_HTTPPOST, CURLOT_OBJECT, 0}, - {"HTTPPROXYTUNNEL", CURLOPT_HTTPPROXYTUNNEL, CURLOT_LONG, 0}, - {"HTTP_CONTENT_DECODING", CURLOPT_HTTP_CONTENT_DECODING, CURLOT_LONG, 0}, - {"HTTP_TRANSFER_DECODING", CURLOPT_HTTP_TRANSFER_DECODING, CURLOT_LONG, 0}, - {"HTTP_VERSION", CURLOPT_HTTP_VERSION, CURLOT_VALUES, 0}, - {"IGNORE_CONTENT_LENGTH", CURLOPT_IGNORE_CONTENT_LENGTH, CURLOT_LONG, 0}, - {"INFILE", CURLOPT_READDATA, CURLOT_CBPTR, CURLOT_FLAG_ALIAS}, - {"INFILESIZE", CURLOPT_INFILESIZE, CURLOT_LONG, 0}, - {"INFILESIZE_LARGE", CURLOPT_INFILESIZE_LARGE, CURLOT_OFF_T, 0}, - {"INTERFACE", CURLOPT_INTERFACE, CURLOT_STRING, 0}, - {"INTERLEAVEDATA", CURLOPT_INTERLEAVEDATA, CURLOT_CBPTR, 0}, - {"INTERLEAVEFUNCTION", CURLOPT_INTERLEAVEFUNCTION, CURLOT_FUNCTION, 0}, - {"IOCTLDATA", CURLOPT_IOCTLDATA, CURLOT_CBPTR, 0}, - {"IOCTLFUNCTION", CURLOPT_IOCTLFUNCTION, CURLOT_FUNCTION, 0}, - {"IPRESOLVE", CURLOPT_IPRESOLVE, CURLOT_VALUES, 0}, - {"ISSUERCERT", CURLOPT_ISSUERCERT, CURLOT_STRING, 0}, - {"ISSUERCERT_BLOB", CURLOPT_ISSUERCERT_BLOB, CURLOT_BLOB, 0}, - {"KEEP_SENDING_ON_ERROR", CURLOPT_KEEP_SENDING_ON_ERROR, CURLOT_LONG, 0}, - {"KEYPASSWD", CURLOPT_KEYPASSWD, CURLOT_STRING, 0}, - {"KRB4LEVEL", CURLOPT_KRBLEVEL, CURLOT_STRING, CURLOT_FLAG_ALIAS}, - {"KRBLEVEL", CURLOPT_KRBLEVEL, CURLOT_STRING, 0}, - {"LOCALPORT", CURLOPT_LOCALPORT, CURLOT_LONG, 0}, - {"LOCALPORTRANGE", CURLOPT_LOCALPORTRANGE, CURLOT_LONG, 0}, - {"LOGIN_OPTIONS", CURLOPT_LOGIN_OPTIONS, CURLOT_STRING, 0}, - {"LOW_SPEED_LIMIT", CURLOPT_LOW_SPEED_LIMIT, CURLOT_LONG, 0}, - {"LOW_SPEED_TIME", CURLOPT_LOW_SPEED_TIME, CURLOT_LONG, 0}, - {"MAIL_AUTH", CURLOPT_MAIL_AUTH, CURLOT_STRING, 0}, - {"MAIL_FROM", CURLOPT_MAIL_FROM, CURLOT_STRING, 0}, - {"MAIL_RCPT", CURLOPT_MAIL_RCPT, CURLOT_SLIST, 0}, - {"MAIL_RCPT_ALLLOWFAILS", CURLOPT_MAIL_RCPT_ALLOWFAILS, - CURLOT_LONG, CURLOT_FLAG_ALIAS}, - {"MAIL_RCPT_ALLOWFAILS", CURLOPT_MAIL_RCPT_ALLOWFAILS, CURLOT_LONG, 0}, - {"MAXAGE_CONN", CURLOPT_MAXAGE_CONN, CURLOT_LONG, 0}, - {"MAXCONNECTS", CURLOPT_MAXCONNECTS, CURLOT_LONG, 0}, - {"MAXFILESIZE", CURLOPT_MAXFILESIZE, CURLOT_LONG, 0}, - {"MAXFILESIZE_LARGE", CURLOPT_MAXFILESIZE_LARGE, CURLOT_OFF_T, 0}, - {"MAXLIFETIME_CONN", CURLOPT_MAXLIFETIME_CONN, CURLOT_LONG, 0}, - {"MAXREDIRS", CURLOPT_MAXREDIRS, CURLOT_LONG, 0}, - {"MAX_RECV_SPEED_LARGE", CURLOPT_MAX_RECV_SPEED_LARGE, CURLOT_OFF_T, 0}, - {"MAX_SEND_SPEED_LARGE", CURLOPT_MAX_SEND_SPEED_LARGE, CURLOT_OFF_T, 0}, - {"MIMEPOST", CURLOPT_MIMEPOST, CURLOT_OBJECT, 0}, - {"MIME_OPTIONS", CURLOPT_MIME_OPTIONS, CURLOT_LONG, 0}, - {"NETRC", CURLOPT_NETRC, CURLOT_VALUES, 0}, - {"NETRC_FILE", CURLOPT_NETRC_FILE, CURLOT_STRING, 0}, - {"NEW_DIRECTORY_PERMS", CURLOPT_NEW_DIRECTORY_PERMS, CURLOT_LONG, 0}, - {"NEW_FILE_PERMS", CURLOPT_NEW_FILE_PERMS, CURLOT_LONG, 0}, - {"NOBODY", CURLOPT_NOBODY, CURLOT_LONG, 0}, - {"NOPROGRESS", CURLOPT_NOPROGRESS, CURLOT_LONG, 0}, - {"NOPROXY", CURLOPT_NOPROXY, CURLOT_STRING, 0}, - {"NOSIGNAL", CURLOPT_NOSIGNAL, CURLOT_LONG, 0}, - {"OPENSOCKETDATA", CURLOPT_OPENSOCKETDATA, CURLOT_CBPTR, 0}, - {"OPENSOCKETFUNCTION", CURLOPT_OPENSOCKETFUNCTION, CURLOT_FUNCTION, 0}, - {"PASSWORD", CURLOPT_PASSWORD, CURLOT_STRING, 0}, - {"PATH_AS_IS", CURLOPT_PATH_AS_IS, CURLOT_LONG, 0}, - {"PINNEDPUBLICKEY", CURLOPT_PINNEDPUBLICKEY, CURLOT_STRING, 0}, - {"PIPEWAIT", CURLOPT_PIPEWAIT, CURLOT_LONG, 0}, - {"PORT", CURLOPT_PORT, CURLOT_LONG, 0}, - {"POST", CURLOPT_POST, CURLOT_LONG, 0}, - {"POST301", CURLOPT_POSTREDIR, CURLOT_VALUES, CURLOT_FLAG_ALIAS}, - {"POSTFIELDS", CURLOPT_POSTFIELDS, CURLOT_OBJECT, 0}, - {"POSTFIELDSIZE", CURLOPT_POSTFIELDSIZE, CURLOT_LONG, 0}, - {"POSTFIELDSIZE_LARGE", CURLOPT_POSTFIELDSIZE_LARGE, CURLOT_OFF_T, 0}, - {"POSTQUOTE", CURLOPT_POSTQUOTE, CURLOT_SLIST, 0}, - {"POSTREDIR", CURLOPT_POSTREDIR, CURLOT_VALUES, 0}, - {"PREQUOTE", CURLOPT_PREQUOTE, CURLOT_SLIST, 0}, - {"PREREQDATA", CURLOPT_PREREQDATA, CURLOT_CBPTR, 0}, - {"PREREQFUNCTION", CURLOPT_PREREQFUNCTION, CURLOT_FUNCTION, 0}, - {"PRE_PROXY", CURLOPT_PRE_PROXY, CURLOT_STRING, 0}, - {"PRIVATE", CURLOPT_PRIVATE, CURLOT_OBJECT, 0}, - {"PROGRESSDATA", CURLOPT_XFERINFODATA, CURLOT_CBPTR, CURLOT_FLAG_ALIAS}, - {"PROGRESSFUNCTION", CURLOPT_PROGRESSFUNCTION, CURLOT_FUNCTION, 0}, - {"PROTOCOLS", CURLOPT_PROTOCOLS, CURLOT_LONG, 0}, - {"PROTOCOLS_STR", CURLOPT_PROTOCOLS_STR, CURLOT_STRING, 0}, - {"PROXY", CURLOPT_PROXY, CURLOT_STRING, 0}, - {"PROXYAUTH", CURLOPT_PROXYAUTH, CURLOT_VALUES, 0}, - {"PROXYHEADER", CURLOPT_PROXYHEADER, CURLOT_SLIST, 0}, - {"PROXYPASSWORD", CURLOPT_PROXYPASSWORD, CURLOT_STRING, 0}, - {"PROXYPORT", CURLOPT_PROXYPORT, CURLOT_LONG, 0}, - {"PROXYTYPE", CURLOPT_PROXYTYPE, CURLOT_VALUES, 0}, - {"PROXYUSERNAME", CURLOPT_PROXYUSERNAME, CURLOT_STRING, 0}, - {"PROXYUSERPWD", CURLOPT_PROXYUSERPWD, CURLOT_STRING, 0}, - {"PROXY_CAINFO", CURLOPT_PROXY_CAINFO, CURLOT_STRING, 0}, - {"PROXY_CAINFO_BLOB", CURLOPT_PROXY_CAINFO_BLOB, CURLOT_BLOB, 0}, - {"PROXY_CAPATH", CURLOPT_PROXY_CAPATH, CURLOT_STRING, 0}, - {"PROXY_CRLFILE", CURLOPT_PROXY_CRLFILE, CURLOT_STRING, 0}, - {"PROXY_ISSUERCERT", CURLOPT_PROXY_ISSUERCERT, CURLOT_STRING, 0}, - {"PROXY_ISSUERCERT_BLOB", CURLOPT_PROXY_ISSUERCERT_BLOB, CURLOT_BLOB, 0}, - {"PROXY_KEYPASSWD", CURLOPT_PROXY_KEYPASSWD, CURLOT_STRING, 0}, - {"PROXY_PINNEDPUBLICKEY", CURLOPT_PROXY_PINNEDPUBLICKEY, CURLOT_STRING, 0}, - {"PROXY_SERVICE_NAME", CURLOPT_PROXY_SERVICE_NAME, CURLOT_STRING, 0}, - {"PROXY_SSLCERT", CURLOPT_PROXY_SSLCERT, CURLOT_STRING, 0}, - {"PROXY_SSLCERTTYPE", CURLOPT_PROXY_SSLCERTTYPE, CURLOT_STRING, 0}, - {"PROXY_SSLCERT_BLOB", CURLOPT_PROXY_SSLCERT_BLOB, CURLOT_BLOB, 0}, - {"PROXY_SSLKEY", CURLOPT_PROXY_SSLKEY, CURLOT_STRING, 0}, - {"PROXY_SSLKEYTYPE", CURLOPT_PROXY_SSLKEYTYPE, CURLOT_STRING, 0}, - {"PROXY_SSLKEY_BLOB", CURLOPT_PROXY_SSLKEY_BLOB, CURLOT_BLOB, 0}, - {"PROXY_SSLVERSION", CURLOPT_PROXY_SSLVERSION, CURLOT_VALUES, 0}, - {"PROXY_SSL_CIPHER_LIST", CURLOPT_PROXY_SSL_CIPHER_LIST, CURLOT_STRING, 0}, - {"PROXY_SSL_OPTIONS", CURLOPT_PROXY_SSL_OPTIONS, CURLOT_LONG, 0}, - {"PROXY_SSL_VERIFYHOST", CURLOPT_PROXY_SSL_VERIFYHOST, CURLOT_LONG, 0}, - {"PROXY_SSL_VERIFYPEER", CURLOPT_PROXY_SSL_VERIFYPEER, CURLOT_LONG, 0}, - {"PROXY_TLS13_CIPHERS", CURLOPT_PROXY_TLS13_CIPHERS, CURLOT_STRING, 0}, - {"PROXY_TLSAUTH_PASSWORD", CURLOPT_PROXY_TLSAUTH_PASSWORD, - CURLOT_STRING, 0}, - {"PROXY_TLSAUTH_TYPE", CURLOPT_PROXY_TLSAUTH_TYPE, CURLOT_STRING, 0}, - {"PROXY_TLSAUTH_USERNAME", CURLOPT_PROXY_TLSAUTH_USERNAME, - CURLOT_STRING, 0}, - {"PROXY_TRANSFER_MODE", CURLOPT_PROXY_TRANSFER_MODE, CURLOT_LONG, 0}, - {"PUT", CURLOPT_PUT, CURLOT_LONG, 0}, - {"QUICK_EXIT", CURLOPT_QUICK_EXIT, CURLOT_LONG, 0}, - {"QUOTE", CURLOPT_QUOTE, CURLOT_SLIST, 0}, - {"RANDOM_FILE", CURLOPT_RANDOM_FILE, CURLOT_STRING, 0}, - {"RANGE", CURLOPT_RANGE, CURLOT_STRING, 0}, - {"READDATA", CURLOPT_READDATA, CURLOT_CBPTR, 0}, - {"READFUNCTION", CURLOPT_READFUNCTION, CURLOT_FUNCTION, 0}, - {"REDIR_PROTOCOLS", CURLOPT_REDIR_PROTOCOLS, CURLOT_LONG, 0}, - {"REDIR_PROTOCOLS_STR", CURLOPT_REDIR_PROTOCOLS_STR, CURLOT_STRING, 0}, - {"REFERER", CURLOPT_REFERER, CURLOT_STRING, 0}, - {"REQUEST_TARGET", CURLOPT_REQUEST_TARGET, CURLOT_STRING, 0}, - {"RESOLVE", CURLOPT_RESOLVE, CURLOT_SLIST, 0}, - {"RESOLVER_START_DATA", CURLOPT_RESOLVER_START_DATA, CURLOT_CBPTR, 0}, - {"RESOLVER_START_FUNCTION", CURLOPT_RESOLVER_START_FUNCTION, - CURLOT_FUNCTION, 0}, - {"RESUME_FROM", CURLOPT_RESUME_FROM, CURLOT_LONG, 0}, - {"RESUME_FROM_LARGE", CURLOPT_RESUME_FROM_LARGE, CURLOT_OFF_T, 0}, - {"RTSPHEADER", CURLOPT_HTTPHEADER, CURLOT_SLIST, CURLOT_FLAG_ALIAS}, - {"RTSP_CLIENT_CSEQ", CURLOPT_RTSP_CLIENT_CSEQ, CURLOT_LONG, 0}, - {"RTSP_REQUEST", CURLOPT_RTSP_REQUEST, CURLOT_VALUES, 0}, - {"RTSP_SERVER_CSEQ", CURLOPT_RTSP_SERVER_CSEQ, CURLOT_LONG, 0}, - {"RTSP_SESSION_ID", CURLOPT_RTSP_SESSION_ID, CURLOT_STRING, 0}, - {"RTSP_STREAM_URI", CURLOPT_RTSP_STREAM_URI, CURLOT_STRING, 0}, - {"RTSP_TRANSPORT", CURLOPT_RTSP_TRANSPORT, CURLOT_STRING, 0}, - {"SASL_AUTHZID", CURLOPT_SASL_AUTHZID, CURLOT_STRING, 0}, - {"SASL_IR", CURLOPT_SASL_IR, CURLOT_LONG, 0}, - {"SEEKDATA", CURLOPT_SEEKDATA, CURLOT_CBPTR, 0}, - {"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}, - {"SOCKOPTFUNCTION", CURLOPT_SOCKOPTFUNCTION, CURLOT_FUNCTION, 0}, - {"SOCKS5_AUTH", CURLOPT_SOCKS5_AUTH, CURLOT_LONG, 0}, - {"SOCKS5_GSSAPI_NEC", CURLOPT_SOCKS5_GSSAPI_NEC, CURLOT_LONG, 0}, - {"SOCKS5_GSSAPI_SERVICE", CURLOPT_SOCKS5_GSSAPI_SERVICE, CURLOT_STRING, 0}, - {"SSH_AUTH_TYPES", CURLOPT_SSH_AUTH_TYPES, CURLOT_VALUES, 0}, - {"SSH_COMPRESSION", CURLOPT_SSH_COMPRESSION, CURLOT_LONG, 0}, - {"SSH_HOSTKEYDATA", CURLOPT_SSH_HOSTKEYDATA, CURLOT_CBPTR, 0}, - {"SSH_HOSTKEYFUNCTION", CURLOPT_SSH_HOSTKEYFUNCTION, CURLOT_FUNCTION, 0}, - {"SSH_HOST_PUBLIC_KEY_MD5", CURLOPT_SSH_HOST_PUBLIC_KEY_MD5, - CURLOT_STRING, 0}, - {"SSH_HOST_PUBLIC_KEY_SHA256", CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256, - CURLOT_STRING, 0}, - {"SSH_KEYDATA", CURLOPT_SSH_KEYDATA, CURLOT_CBPTR, 0}, - {"SSH_KEYFUNCTION", CURLOPT_SSH_KEYFUNCTION, CURLOT_FUNCTION, 0}, - {"SSH_KNOWNHOSTS", CURLOPT_SSH_KNOWNHOSTS, CURLOT_STRING, 0}, - {"SSH_PRIVATE_KEYFILE", CURLOPT_SSH_PRIVATE_KEYFILE, CURLOT_STRING, 0}, - {"SSH_PUBLIC_KEYFILE", CURLOPT_SSH_PUBLIC_KEYFILE, CURLOT_STRING, 0}, - {"SSLCERT", CURLOPT_SSLCERT, CURLOT_STRING, 0}, - {"SSLCERTPASSWD", CURLOPT_KEYPASSWD, CURLOT_STRING, CURLOT_FLAG_ALIAS}, - {"SSLCERTTYPE", CURLOPT_SSLCERTTYPE, CURLOT_STRING, 0}, - {"SSLCERT_BLOB", CURLOPT_SSLCERT_BLOB, CURLOT_BLOB, 0}, - {"SSLENGINE", CURLOPT_SSLENGINE, CURLOT_STRING, 0}, - {"SSLENGINE_DEFAULT", CURLOPT_SSLENGINE_DEFAULT, CURLOT_LONG, 0}, - {"SSLKEY", CURLOPT_SSLKEY, CURLOT_STRING, 0}, - {"SSLKEYPASSWD", CURLOPT_KEYPASSWD, CURLOT_STRING, CURLOT_FLAG_ALIAS}, - {"SSLKEYTYPE", CURLOPT_SSLKEYTYPE, CURLOT_STRING, 0}, - {"SSLKEY_BLOB", CURLOPT_SSLKEY_BLOB, CURLOT_BLOB, 0}, - {"SSLVERSION", CURLOPT_SSLVERSION, CURLOT_VALUES, 0}, - {"SSL_CIPHER_LIST", CURLOPT_SSL_CIPHER_LIST, CURLOT_STRING, 0}, - {"SSL_CTX_DATA", CURLOPT_SSL_CTX_DATA, CURLOT_CBPTR, 0}, - {"SSL_CTX_FUNCTION", CURLOPT_SSL_CTX_FUNCTION, CURLOT_FUNCTION, 0}, - {"SSL_EC_CURVES", CURLOPT_SSL_EC_CURVES, CURLOT_STRING, 0}, - {"SSL_ENABLE_ALPN", CURLOPT_SSL_ENABLE_ALPN, CURLOT_LONG, 0}, - {"SSL_ENABLE_NPN", CURLOPT_SSL_ENABLE_NPN, CURLOT_LONG, 0}, - {"SSL_FALSESTART", CURLOPT_SSL_FALSESTART, CURLOT_LONG, 0}, - {"SSL_OPTIONS", CURLOPT_SSL_OPTIONS, CURLOT_VALUES, 0}, - {"SSL_SESSIONID_CACHE", CURLOPT_SSL_SESSIONID_CACHE, CURLOT_LONG, 0}, - {"SSL_SIGNATURE_ALGORITHMS", CURLOPT_SSL_SIGNATURE_ALGORITHMS, - CURLOT_STRING, 0}, - {"SSL_VERIFYHOST", CURLOPT_SSL_VERIFYHOST, CURLOT_LONG, 0}, - {"SSL_VERIFYPEER", CURLOPT_SSL_VERIFYPEER, CURLOT_LONG, 0}, - {"SSL_VERIFYSTATUS", CURLOPT_SSL_VERIFYSTATUS, CURLOT_LONG, 0}, - {"STDERR", CURLOPT_STDERR, CURLOT_OBJECT, 0}, - {"STREAM_DEPENDS", CURLOPT_STREAM_DEPENDS, CURLOT_OBJECT, 0}, - {"STREAM_DEPENDS_E", CURLOPT_STREAM_DEPENDS_E, CURLOT_OBJECT, 0}, - {"STREAM_WEIGHT", CURLOPT_STREAM_WEIGHT, CURLOT_LONG, 0}, - {"SUPPRESS_CONNECT_HEADERS", CURLOPT_SUPPRESS_CONNECT_HEADERS, - CURLOT_LONG, 0}, - {"TCP_FASTOPEN", CURLOPT_TCP_FASTOPEN, CURLOT_LONG, 0}, - {"TCP_KEEPALIVE", CURLOPT_TCP_KEEPALIVE, CURLOT_LONG, 0}, - {"TCP_KEEPCNT", CURLOPT_TCP_KEEPCNT, CURLOT_LONG, 0}, - {"TCP_KEEPIDLE", CURLOPT_TCP_KEEPIDLE, CURLOT_LONG, 0}, - {"TCP_KEEPINTVL", CURLOPT_TCP_KEEPINTVL, CURLOT_LONG, 0}, - {"TCP_NODELAY", CURLOPT_TCP_NODELAY, CURLOT_LONG, 0}, - {"TELNETOPTIONS", CURLOPT_TELNETOPTIONS, CURLOT_SLIST, 0}, - {"TFTP_BLKSIZE", CURLOPT_TFTP_BLKSIZE, CURLOT_LONG, 0}, - {"TFTP_NO_OPTIONS", CURLOPT_TFTP_NO_OPTIONS, CURLOT_LONG, 0}, - {"TIMECONDITION", CURLOPT_TIMECONDITION, CURLOT_VALUES, 0}, - {"TIMEOUT", CURLOPT_TIMEOUT, CURLOT_LONG, 0}, - {"TIMEOUT_MS", CURLOPT_TIMEOUT_MS, CURLOT_LONG, 0}, - {"TIMEVALUE", CURLOPT_TIMEVALUE, CURLOT_LONG, 0}, - {"TIMEVALUE_LARGE", CURLOPT_TIMEVALUE_LARGE, CURLOT_OFF_T, 0}, - {"TLS13_CIPHERS", CURLOPT_TLS13_CIPHERS, CURLOT_STRING, 0}, - {"TLSAUTH_PASSWORD", CURLOPT_TLSAUTH_PASSWORD, CURLOT_STRING, 0}, - {"TLSAUTH_TYPE", CURLOPT_TLSAUTH_TYPE, CURLOT_STRING, 0}, - {"TLSAUTH_USERNAME", CURLOPT_TLSAUTH_USERNAME, CURLOT_STRING, 0}, - {"TRAILERDATA", CURLOPT_TRAILERDATA, CURLOT_CBPTR, 0}, - {"TRAILERFUNCTION", CURLOPT_TRAILERFUNCTION, CURLOT_FUNCTION, 0}, - {"TRANSFERTEXT", CURLOPT_TRANSFERTEXT, CURLOT_LONG, 0}, - {"TRANSFER_ENCODING", CURLOPT_TRANSFER_ENCODING, CURLOT_LONG, 0}, - {"UNIX_SOCKET_PATH", CURLOPT_UNIX_SOCKET_PATH, CURLOT_STRING, 0}, - {"UNRESTRICTED_AUTH", CURLOPT_UNRESTRICTED_AUTH, CURLOT_LONG, 0}, - {"UPKEEP_INTERVAL_MS", CURLOPT_UPKEEP_INTERVAL_MS, CURLOT_LONG, 0}, - {"UPLOAD", CURLOPT_UPLOAD, CURLOT_LONG, 0}, - {"UPLOAD_BUFFERSIZE", CURLOPT_UPLOAD_BUFFERSIZE, CURLOT_LONG, 0}, - {"UPLOAD_FLAGS", CURLOPT_UPLOAD_FLAGS, CURLOT_LONG, 0}, - {"URL", CURLOPT_URL, CURLOT_STRING, 0}, - {"USERAGENT", CURLOPT_USERAGENT, CURLOT_STRING, 0}, - {"USERNAME", CURLOPT_USERNAME, CURLOT_STRING, 0}, - {"USERPWD", CURLOPT_USERPWD, CURLOT_STRING, 0}, - {"USE_SSL", CURLOPT_USE_SSL, CURLOT_VALUES, 0}, - {"VERBOSE", CURLOPT_VERBOSE, CURLOT_LONG, 0}, - {"WILDCARDMATCH", CURLOPT_WILDCARDMATCH, CURLOT_LONG, 0}, - {"WRITEDATA", CURLOPT_WRITEDATA, CURLOT_CBPTR, 0}, - {"WRITEFUNCTION", CURLOPT_WRITEFUNCTION, CURLOT_FUNCTION, 0}, - {"WRITEHEADER", CURLOPT_HEADERDATA, CURLOT_CBPTR, CURLOT_FLAG_ALIAS}, - {"WS_OPTIONS", CURLOPT_WS_OPTIONS, CURLOT_LONG, 0}, - {"XFERINFODATA", CURLOPT_XFERINFODATA, CURLOT_CBPTR, 0}, - {"XFERINFOFUNCTION", CURLOPT_XFERINFOFUNCTION, CURLOT_FUNCTION, 0}, - {"XOAUTH2_BEARER", CURLOPT_XOAUTH2_BEARER, CURLOT_STRING, 0}, - {NULL, CURLOPT_LASTENTRY, CURLOT_LONG, 0} /* end of table */ + { "ABSTRACT_UNIX_SOCKET", CURLOPT_ABSTRACT_UNIX_SOCKET, CURLOT_STRING, 0 }, + { "ACCEPTTIMEOUT_MS", CURLOPT_ACCEPTTIMEOUT_MS, CURLOT_LONG, 0 }, + { "ACCEPT_ENCODING", CURLOPT_ACCEPT_ENCODING, CURLOT_STRING, 0 }, + { "ADDRESS_SCOPE", CURLOPT_ADDRESS_SCOPE, CURLOT_LONG, 0 }, + { "ALTSVC", CURLOPT_ALTSVC, CURLOT_STRING, 0 }, + { "ALTSVC_CTRL", CURLOPT_ALTSVC_CTRL, CURLOT_LONG, 0 }, + { "APPEND", CURLOPT_APPEND, CURLOT_LONG, 0 }, + { "AUTOREFERER", CURLOPT_AUTOREFERER, CURLOT_LONG, 0 }, + { "AWS_SIGV4", CURLOPT_AWS_SIGV4, CURLOT_STRING, 0 }, + { "BUFFERSIZE", CURLOPT_BUFFERSIZE, CURLOT_LONG, 0 }, + { "CAINFO", CURLOPT_CAINFO, CURLOT_STRING, 0 }, + { "CAINFO_BLOB", CURLOPT_CAINFO_BLOB, CURLOT_BLOB, 0 }, + { "CAPATH", CURLOPT_CAPATH, CURLOT_STRING, 0 }, + { "CA_CACHE_TIMEOUT", CURLOPT_CA_CACHE_TIMEOUT, CURLOT_LONG, 0 }, + { "CERTINFO", CURLOPT_CERTINFO, CURLOT_LONG, 0 }, + { "CHUNK_BGN_FUNCTION", CURLOPT_CHUNK_BGN_FUNCTION, CURLOT_FUNCTION, 0 }, + { "CHUNK_DATA", CURLOPT_CHUNK_DATA, CURLOT_CBPTR, 0 }, + { "CHUNK_END_FUNCTION", CURLOPT_CHUNK_END_FUNCTION, CURLOT_FUNCTION, 0 }, + { "CLOSESOCKETDATA", CURLOPT_CLOSESOCKETDATA, CURLOT_CBPTR, 0 }, + { "CLOSESOCKETFUNCTION", CURLOPT_CLOSESOCKETFUNCTION, CURLOT_FUNCTION, 0 }, + { "CONNECTTIMEOUT", CURLOPT_CONNECTTIMEOUT, CURLOT_LONG, 0 }, + { "CONNECTTIMEOUT_MS", CURLOPT_CONNECTTIMEOUT_MS, CURLOT_LONG, 0 }, + { "CONNECT_ONLY", CURLOPT_CONNECT_ONLY, CURLOT_LONG, 0 }, + { "CONNECT_TO", CURLOPT_CONNECT_TO, CURLOT_SLIST, 0 }, + { "CONV_FROM_NETWORK_FUNCTION", CURLOPT_CONV_FROM_NETWORK_FUNCTION, + CURLOT_FUNCTION, 0 }, + { "CONV_FROM_UTF8_FUNCTION", CURLOPT_CONV_FROM_UTF8_FUNCTION, + CURLOT_FUNCTION, 0 }, + { "CONV_TO_NETWORK_FUNCTION", CURLOPT_CONV_TO_NETWORK_FUNCTION, + CURLOT_FUNCTION, 0 }, + { "COOKIE", CURLOPT_COOKIE, CURLOT_STRING, 0 }, + { "COOKIEFILE", CURLOPT_COOKIEFILE, CURLOT_STRING, 0 }, + { "COOKIEJAR", CURLOPT_COOKIEJAR, CURLOT_STRING, 0 }, + { "COOKIELIST", CURLOPT_COOKIELIST, CURLOT_STRING, 0 }, + { "COOKIESESSION", CURLOPT_COOKIESESSION, CURLOT_LONG, 0 }, + { "COPYPOSTFIELDS", CURLOPT_COPYPOSTFIELDS, CURLOT_OBJECT, 0 }, + { "CRLF", CURLOPT_CRLF, CURLOT_LONG, 0 }, + { "CRLFILE", CURLOPT_CRLFILE, CURLOT_STRING, 0 }, + { "CURLU", CURLOPT_CURLU, CURLOT_OBJECT, 0 }, + { "CUSTOMREQUEST", CURLOPT_CUSTOMREQUEST, CURLOT_STRING, 0 }, + { "DEBUGDATA", CURLOPT_DEBUGDATA, CURLOT_CBPTR, 0 }, + { "DEBUGFUNCTION", CURLOPT_DEBUGFUNCTION, CURLOT_FUNCTION, 0 }, + { "DEFAULT_PROTOCOL", CURLOPT_DEFAULT_PROTOCOL, CURLOT_STRING, 0 }, + { "DIRLISTONLY", CURLOPT_DIRLISTONLY, CURLOT_LONG, 0 }, + { "DISALLOW_USERNAME_IN_URL", CURLOPT_DISALLOW_USERNAME_IN_URL, + CURLOT_LONG, 0 }, + { "DNS_CACHE_TIMEOUT", CURLOPT_DNS_CACHE_TIMEOUT, CURLOT_LONG, 0 }, + { "DNS_INTERFACE", CURLOPT_DNS_INTERFACE, CURLOT_STRING, 0 }, + { "DNS_LOCAL_IP4", CURLOPT_DNS_LOCAL_IP4, CURLOT_STRING, 0 }, + { "DNS_LOCAL_IP6", CURLOPT_DNS_LOCAL_IP6, CURLOT_STRING, 0 }, + { "DNS_SERVERS", CURLOPT_DNS_SERVERS, CURLOT_STRING, 0 }, + { "DNS_SHUFFLE_ADDRESSES", CURLOPT_DNS_SHUFFLE_ADDRESSES, CURLOT_LONG, 0 }, + { "DNS_USE_GLOBAL_CACHE", CURLOPT_DNS_USE_GLOBAL_CACHE, CURLOT_LONG, 0 }, + { "DOH_SSL_VERIFYHOST", CURLOPT_DOH_SSL_VERIFYHOST, CURLOT_LONG, 0 }, + { "DOH_SSL_VERIFYPEER", CURLOPT_DOH_SSL_VERIFYPEER, CURLOT_LONG, 0 }, + { "DOH_SSL_VERIFYSTATUS", CURLOPT_DOH_SSL_VERIFYSTATUS, CURLOT_LONG, 0 }, + { "DOH_URL", CURLOPT_DOH_URL, CURLOT_STRING, 0 }, + { "ECH", CURLOPT_ECH, CURLOT_STRING, 0 }, + { "EGDSOCKET", CURLOPT_EGDSOCKET, CURLOT_STRING, 0 }, + { "ENCODING", CURLOPT_ACCEPT_ENCODING, CURLOT_STRING, CURLOT_FLAG_ALIAS }, + { "ERRORBUFFER", CURLOPT_ERRORBUFFER, CURLOT_OBJECT, 0 }, + { "EXPECT_100_TIMEOUT_MS", CURLOPT_EXPECT_100_TIMEOUT_MS, CURLOT_LONG, 0 }, + { "FAILONERROR", CURLOPT_FAILONERROR, CURLOT_LONG, 0 }, + { "FILE", CURLOPT_WRITEDATA, CURLOT_CBPTR, CURLOT_FLAG_ALIAS }, + { "FILETIME", CURLOPT_FILETIME, CURLOT_LONG, 0 }, + { "FNMATCH_DATA", CURLOPT_FNMATCH_DATA, CURLOT_CBPTR, 0 }, + { "FNMATCH_FUNCTION", CURLOPT_FNMATCH_FUNCTION, CURLOT_FUNCTION, 0 }, + { "FOLLOWLOCATION", CURLOPT_FOLLOWLOCATION, CURLOT_LONG, 0 }, + { "FORBID_REUSE", CURLOPT_FORBID_REUSE, CURLOT_LONG, 0 }, + { "FRESH_CONNECT", CURLOPT_FRESH_CONNECT, CURLOT_LONG, 0 }, + { "FTPAPPEND", CURLOPT_APPEND, CURLOT_LONG, CURLOT_FLAG_ALIAS }, + { "FTPLISTONLY", CURLOPT_DIRLISTONLY, CURLOT_LONG, CURLOT_FLAG_ALIAS }, + { "FTPPORT", CURLOPT_FTPPORT, CURLOT_STRING, 0 }, + { "FTPSSLAUTH", CURLOPT_FTPSSLAUTH, CURLOT_VALUES, 0 }, + { "FTP_ACCOUNT", CURLOPT_FTP_ACCOUNT, CURLOT_STRING, 0 }, + { "FTP_ALTERNATIVE_TO_USER", CURLOPT_FTP_ALTERNATIVE_TO_USER, + CURLOT_STRING, 0 }, + { "FTP_CREATE_MISSING_DIRS", CURLOPT_FTP_CREATE_MISSING_DIRS, + CURLOT_LONG, 0 }, + { "FTP_FILEMETHOD", CURLOPT_FTP_FILEMETHOD, CURLOT_VALUES, 0 }, + { "FTP_RESPONSE_TIMEOUT", CURLOPT_SERVER_RESPONSE_TIMEOUT, + CURLOT_LONG, CURLOT_FLAG_ALIAS }, + { "FTP_SKIP_PASV_IP", CURLOPT_FTP_SKIP_PASV_IP, CURLOT_LONG, 0 }, + { "FTP_SSL", CURLOPT_USE_SSL, CURLOT_VALUES, CURLOT_FLAG_ALIAS }, + { "FTP_SSL_CCC", CURLOPT_FTP_SSL_CCC, CURLOT_LONG, 0 }, + { "FTP_USE_EPRT", CURLOPT_FTP_USE_EPRT, CURLOT_LONG, 0 }, + { "FTP_USE_EPSV", CURLOPT_FTP_USE_EPSV, CURLOT_LONG, 0 }, + { "FTP_USE_PRET", CURLOPT_FTP_USE_PRET, CURLOT_LONG, 0 }, + { "GSSAPI_DELEGATION", CURLOPT_GSSAPI_DELEGATION, CURLOT_VALUES, 0 }, + { "HAPPY_EYEBALLS_TIMEOUT_MS", CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS, + CURLOT_LONG, 0 }, + { "HAPROXYPROTOCOL", CURLOPT_HAPROXYPROTOCOL, CURLOT_LONG, 0 }, + { "HAPROXY_CLIENT_IP", CURLOPT_HAPROXY_CLIENT_IP, CURLOT_STRING, 0 }, + { "HEADER", CURLOPT_HEADER, CURLOT_LONG, 0 }, + { "HEADERDATA", CURLOPT_HEADERDATA, CURLOT_CBPTR, 0 }, + { "HEADERFUNCTION", CURLOPT_HEADERFUNCTION, CURLOT_FUNCTION, 0 }, + { "HEADEROPT", CURLOPT_HEADEROPT, CURLOT_VALUES, 0 }, + { "HSTS", CURLOPT_HSTS, CURLOT_STRING, 0 }, + { "HSTSREADDATA", CURLOPT_HSTSREADDATA, CURLOT_CBPTR, 0 }, + { "HSTSREADFUNCTION", CURLOPT_HSTSREADFUNCTION, CURLOT_FUNCTION, 0 }, + { "HSTSWRITEDATA", CURLOPT_HSTSWRITEDATA, CURLOT_CBPTR, 0 }, + { "HSTSWRITEFUNCTION", CURLOPT_HSTSWRITEFUNCTION, CURLOT_FUNCTION, 0 }, + { "HSTS_CTRL", CURLOPT_HSTS_CTRL, CURLOT_LONG, 0 }, + { "HTTP09_ALLOWED", CURLOPT_HTTP09_ALLOWED, CURLOT_LONG, 0 }, + { "HTTP200ALIASES", CURLOPT_HTTP200ALIASES, CURLOT_SLIST, 0 }, + { "HTTPAUTH", CURLOPT_HTTPAUTH, CURLOT_VALUES, 0 }, + { "HTTPGET", CURLOPT_HTTPGET, CURLOT_LONG, 0 }, + { "HTTPHEADER", CURLOPT_HTTPHEADER, CURLOT_SLIST, 0 }, + { "HTTPPOST", CURLOPT_HTTPPOST, CURLOT_OBJECT, 0 }, + { "HTTPPROXYTUNNEL", CURLOPT_HTTPPROXYTUNNEL, CURLOT_LONG, 0 }, + { "HTTP_CONTENT_DECODING", CURLOPT_HTTP_CONTENT_DECODING, CURLOT_LONG, 0 }, + { "HTTP_TRANSFER_DECODING", CURLOPT_HTTP_TRANSFER_DECODING, + CURLOT_LONG, 0 }, + { "HTTP_VERSION", CURLOPT_HTTP_VERSION, CURLOT_VALUES, 0 }, + { "IGNORE_CONTENT_LENGTH", CURLOPT_IGNORE_CONTENT_LENGTH, CURLOT_LONG, 0 }, + { "INFILE", CURLOPT_READDATA, CURLOT_CBPTR, CURLOT_FLAG_ALIAS }, + { "INFILESIZE", CURLOPT_INFILESIZE, CURLOT_LONG, 0 }, + { "INFILESIZE_LARGE", CURLOPT_INFILESIZE_LARGE, CURLOT_OFF_T, 0 }, + { "INTERFACE", CURLOPT_INTERFACE, CURLOT_STRING, 0 }, + { "INTERLEAVEDATA", CURLOPT_INTERLEAVEDATA, CURLOT_CBPTR, 0 }, + { "INTERLEAVEFUNCTION", CURLOPT_INTERLEAVEFUNCTION, CURLOT_FUNCTION, 0 }, + { "IOCTLDATA", CURLOPT_IOCTLDATA, CURLOT_CBPTR, 0 }, + { "IOCTLFUNCTION", CURLOPT_IOCTLFUNCTION, CURLOT_FUNCTION, 0 }, + { "IPRESOLVE", CURLOPT_IPRESOLVE, CURLOT_VALUES, 0 }, + { "ISSUERCERT", CURLOPT_ISSUERCERT, CURLOT_STRING, 0 }, + { "ISSUERCERT_BLOB", CURLOPT_ISSUERCERT_BLOB, CURLOT_BLOB, 0 }, + { "KEEP_SENDING_ON_ERROR", CURLOPT_KEEP_SENDING_ON_ERROR, CURLOT_LONG, 0 }, + { "KEYPASSWD", CURLOPT_KEYPASSWD, CURLOT_STRING, 0 }, + { "KRB4LEVEL", CURLOPT_KRBLEVEL, CURLOT_STRING, CURLOT_FLAG_ALIAS }, + { "KRBLEVEL", CURLOPT_KRBLEVEL, CURLOT_STRING, 0 }, + { "LOCALPORT", CURLOPT_LOCALPORT, CURLOT_LONG, 0 }, + { "LOCALPORTRANGE", CURLOPT_LOCALPORTRANGE, CURLOT_LONG, 0 }, + { "LOGIN_OPTIONS", CURLOPT_LOGIN_OPTIONS, CURLOT_STRING, 0 }, + { "LOW_SPEED_LIMIT", CURLOPT_LOW_SPEED_LIMIT, CURLOT_LONG, 0 }, + { "LOW_SPEED_TIME", CURLOPT_LOW_SPEED_TIME, CURLOT_LONG, 0 }, + { "MAIL_AUTH", CURLOPT_MAIL_AUTH, CURLOT_STRING, 0 }, + { "MAIL_FROM", CURLOPT_MAIL_FROM, CURLOT_STRING, 0 }, + { "MAIL_RCPT", CURLOPT_MAIL_RCPT, CURLOT_SLIST, 0 }, + { "MAIL_RCPT_ALLLOWFAILS", CURLOPT_MAIL_RCPT_ALLOWFAILS, + CURLOT_LONG, CURLOT_FLAG_ALIAS }, + { "MAIL_RCPT_ALLOWFAILS", CURLOPT_MAIL_RCPT_ALLOWFAILS, CURLOT_LONG, 0 }, + { "MAXAGE_CONN", CURLOPT_MAXAGE_CONN, CURLOT_LONG, 0 }, + { "MAXCONNECTS", CURLOPT_MAXCONNECTS, CURLOT_LONG, 0 }, + { "MAXFILESIZE", CURLOPT_MAXFILESIZE, CURLOT_LONG, 0 }, + { "MAXFILESIZE_LARGE", CURLOPT_MAXFILESIZE_LARGE, CURLOT_OFF_T, 0 }, + { "MAXLIFETIME_CONN", CURLOPT_MAXLIFETIME_CONN, CURLOT_LONG, 0 }, + { "MAXREDIRS", CURLOPT_MAXREDIRS, CURLOT_LONG, 0 }, + { "MAX_RECV_SPEED_LARGE", CURLOPT_MAX_RECV_SPEED_LARGE, CURLOT_OFF_T, 0 }, + { "MAX_SEND_SPEED_LARGE", CURLOPT_MAX_SEND_SPEED_LARGE, CURLOT_OFF_T, 0 }, + { "MIMEPOST", CURLOPT_MIMEPOST, CURLOT_OBJECT, 0 }, + { "MIME_OPTIONS", CURLOPT_MIME_OPTIONS, CURLOT_LONG, 0 }, + { "NETRC", CURLOPT_NETRC, CURLOT_VALUES, 0 }, + { "NETRC_FILE", CURLOPT_NETRC_FILE, CURLOT_STRING, 0 }, + { "NEW_DIRECTORY_PERMS", CURLOPT_NEW_DIRECTORY_PERMS, CURLOT_LONG, 0 }, + { "NEW_FILE_PERMS", CURLOPT_NEW_FILE_PERMS, CURLOT_LONG, 0 }, + { "NOBODY", CURLOPT_NOBODY, CURLOT_LONG, 0 }, + { "NOPROGRESS", CURLOPT_NOPROGRESS, CURLOT_LONG, 0 }, + { "NOPROXY", CURLOPT_NOPROXY, CURLOT_STRING, 0 }, + { "NOSIGNAL", CURLOPT_NOSIGNAL, CURLOT_LONG, 0 }, + { "OPENSOCKETDATA", CURLOPT_OPENSOCKETDATA, CURLOT_CBPTR, 0 }, + { "OPENSOCKETFUNCTION", CURLOPT_OPENSOCKETFUNCTION, CURLOT_FUNCTION, 0 }, + { "PASSWORD", CURLOPT_PASSWORD, CURLOT_STRING, 0 }, + { "PATH_AS_IS", CURLOPT_PATH_AS_IS, CURLOT_LONG, 0 }, + { "PINNEDPUBLICKEY", CURLOPT_PINNEDPUBLICKEY, CURLOT_STRING, 0 }, + { "PIPEWAIT", CURLOPT_PIPEWAIT, CURLOT_LONG, 0 }, + { "PORT", CURLOPT_PORT, CURLOT_LONG, 0 }, + { "POST", CURLOPT_POST, CURLOT_LONG, 0 }, + { "POST301", CURLOPT_POSTREDIR, CURLOT_VALUES, CURLOT_FLAG_ALIAS }, + { "POSTFIELDS", CURLOPT_POSTFIELDS, CURLOT_OBJECT, 0 }, + { "POSTFIELDSIZE", CURLOPT_POSTFIELDSIZE, CURLOT_LONG, 0 }, + { "POSTFIELDSIZE_LARGE", CURLOPT_POSTFIELDSIZE_LARGE, CURLOT_OFF_T, 0 }, + { "POSTQUOTE", CURLOPT_POSTQUOTE, CURLOT_SLIST, 0 }, + { "POSTREDIR", CURLOPT_POSTREDIR, CURLOT_VALUES, 0 }, + { "PREQUOTE", CURLOPT_PREQUOTE, CURLOT_SLIST, 0 }, + { "PREREQDATA", CURLOPT_PREREQDATA, CURLOT_CBPTR, 0 }, + { "PREREQFUNCTION", CURLOPT_PREREQFUNCTION, CURLOT_FUNCTION, 0 }, + { "PRE_PROXY", CURLOPT_PRE_PROXY, CURLOT_STRING, 0 }, + { "PRIVATE", CURLOPT_PRIVATE, CURLOT_OBJECT, 0 }, + { "PROGRESSDATA", CURLOPT_XFERINFODATA, CURLOT_CBPTR, CURLOT_FLAG_ALIAS }, + { "PROGRESSFUNCTION", CURLOPT_PROGRESSFUNCTION, CURLOT_FUNCTION, 0 }, + { "PROTOCOLS", CURLOPT_PROTOCOLS, CURLOT_LONG, 0 }, + { "PROTOCOLS_STR", CURLOPT_PROTOCOLS_STR, CURLOT_STRING, 0 }, + { "PROXY", CURLOPT_PROXY, CURLOT_STRING, 0 }, + { "PROXYAUTH", CURLOPT_PROXYAUTH, CURLOT_VALUES, 0 }, + { "PROXYHEADER", CURLOPT_PROXYHEADER, CURLOT_SLIST, 0 }, + { "PROXYPASSWORD", CURLOPT_PROXYPASSWORD, CURLOT_STRING, 0 }, + { "PROXYPORT", CURLOPT_PROXYPORT, CURLOT_LONG, 0 }, + { "PROXYTYPE", CURLOPT_PROXYTYPE, CURLOT_VALUES, 0 }, + { "PROXYUSERNAME", CURLOPT_PROXYUSERNAME, CURLOT_STRING, 0 }, + { "PROXYUSERPWD", CURLOPT_PROXYUSERPWD, CURLOT_STRING, 0 }, + { "PROXY_CAINFO", CURLOPT_PROXY_CAINFO, CURLOT_STRING, 0 }, + { "PROXY_CAINFO_BLOB", CURLOPT_PROXY_CAINFO_BLOB, CURLOT_BLOB, 0 }, + { "PROXY_CAPATH", CURLOPT_PROXY_CAPATH, CURLOT_STRING, 0 }, + { "PROXY_CRLFILE", CURLOPT_PROXY_CRLFILE, CURLOT_STRING, 0 }, + { "PROXY_ISSUERCERT", CURLOPT_PROXY_ISSUERCERT, CURLOT_STRING, 0 }, + { "PROXY_ISSUERCERT_BLOB", CURLOPT_PROXY_ISSUERCERT_BLOB, CURLOT_BLOB, 0 }, + { "PROXY_KEYPASSWD", CURLOPT_PROXY_KEYPASSWD, CURLOT_STRING, 0 }, + { "PROXY_PINNEDPUBLICKEY", CURLOPT_PROXY_PINNEDPUBLICKEY, + CURLOT_STRING, 0 }, + { "PROXY_SERVICE_NAME", CURLOPT_PROXY_SERVICE_NAME, CURLOT_STRING, 0 }, + { "PROXY_SSLCERT", CURLOPT_PROXY_SSLCERT, CURLOT_STRING, 0 }, + { "PROXY_SSLCERTTYPE", CURLOPT_PROXY_SSLCERTTYPE, CURLOT_STRING, 0 }, + { "PROXY_SSLCERT_BLOB", CURLOPT_PROXY_SSLCERT_BLOB, CURLOT_BLOB, 0 }, + { "PROXY_SSLKEY", CURLOPT_PROXY_SSLKEY, CURLOT_STRING, 0 }, + { "PROXY_SSLKEYTYPE", CURLOPT_PROXY_SSLKEYTYPE, CURLOT_STRING, 0 }, + { "PROXY_SSLKEY_BLOB", CURLOPT_PROXY_SSLKEY_BLOB, CURLOT_BLOB, 0 }, + { "PROXY_SSLVERSION", CURLOPT_PROXY_SSLVERSION, CURLOT_VALUES, 0 }, + { "PROXY_SSL_CIPHER_LIST", CURLOPT_PROXY_SSL_CIPHER_LIST, + CURLOT_STRING, 0 }, + { "PROXY_SSL_OPTIONS", CURLOPT_PROXY_SSL_OPTIONS, CURLOT_LONG, 0 }, + { "PROXY_SSL_VERIFYHOST", CURLOPT_PROXY_SSL_VERIFYHOST, CURLOT_LONG, 0 }, + { "PROXY_SSL_VERIFYPEER", CURLOPT_PROXY_SSL_VERIFYPEER, CURLOT_LONG, 0 }, + { "PROXY_TLS13_CIPHERS", CURLOPT_PROXY_TLS13_CIPHERS, CURLOT_STRING, 0 }, + { "PROXY_TLSAUTH_PASSWORD", CURLOPT_PROXY_TLSAUTH_PASSWORD, + CURLOT_STRING, 0 }, + { "PROXY_TLSAUTH_TYPE", CURLOPT_PROXY_TLSAUTH_TYPE, CURLOT_STRING, 0 }, + { "PROXY_TLSAUTH_USERNAME", CURLOPT_PROXY_TLSAUTH_USERNAME, + CURLOT_STRING, 0 }, + { "PROXY_TRANSFER_MODE", CURLOPT_PROXY_TRANSFER_MODE, CURLOT_LONG, 0 }, + { "PUT", CURLOPT_PUT, CURLOT_LONG, 0 }, + { "QUICK_EXIT", CURLOPT_QUICK_EXIT, CURLOT_LONG, 0 }, + { "QUOTE", CURLOPT_QUOTE, CURLOT_SLIST, 0 }, + { "RANDOM_FILE", CURLOPT_RANDOM_FILE, CURLOT_STRING, 0 }, + { "RANGE", CURLOPT_RANGE, CURLOT_STRING, 0 }, + { "READDATA", CURLOPT_READDATA, CURLOT_CBPTR, 0 }, + { "READFUNCTION", CURLOPT_READFUNCTION, CURLOT_FUNCTION, 0 }, + { "REDIR_PROTOCOLS", CURLOPT_REDIR_PROTOCOLS, CURLOT_LONG, 0 }, + { "REDIR_PROTOCOLS_STR", CURLOPT_REDIR_PROTOCOLS_STR, CURLOT_STRING, 0 }, + { "REFERER", CURLOPT_REFERER, CURLOT_STRING, 0 }, + { "REQUEST_TARGET", CURLOPT_REQUEST_TARGET, CURLOT_STRING, 0 }, + { "RESOLVE", CURLOPT_RESOLVE, CURLOT_SLIST, 0 }, + { "RESOLVER_START_DATA", CURLOPT_RESOLVER_START_DATA, CURLOT_CBPTR, 0 }, + { "RESOLVER_START_FUNCTION", CURLOPT_RESOLVER_START_FUNCTION, + CURLOT_FUNCTION, 0 }, + { "RESUME_FROM", CURLOPT_RESUME_FROM, CURLOT_LONG, 0 }, + { "RESUME_FROM_LARGE", CURLOPT_RESUME_FROM_LARGE, CURLOT_OFF_T, 0 }, + { "RTSPHEADER", CURLOPT_HTTPHEADER, CURLOT_SLIST, CURLOT_FLAG_ALIAS }, + { "RTSP_CLIENT_CSEQ", CURLOPT_RTSP_CLIENT_CSEQ, CURLOT_LONG, 0 }, + { "RTSP_REQUEST", CURLOPT_RTSP_REQUEST, CURLOT_VALUES, 0 }, + { "RTSP_SERVER_CSEQ", CURLOPT_RTSP_SERVER_CSEQ, CURLOT_LONG, 0 }, + { "RTSP_SESSION_ID", CURLOPT_RTSP_SESSION_ID, CURLOT_STRING, 0 }, + { "RTSP_STREAM_URI", CURLOPT_RTSP_STREAM_URI, CURLOT_STRING, 0 }, + { "RTSP_TRANSPORT", CURLOPT_RTSP_TRANSPORT, CURLOT_STRING, 0 }, + { "SASL_AUTHZID", CURLOPT_SASL_AUTHZID, CURLOT_STRING, 0 }, + { "SASL_IR", CURLOPT_SASL_IR, CURLOT_LONG, 0 }, + { "SEEKDATA", CURLOPT_SEEKDATA, CURLOT_CBPTR, 0 }, + { "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 }, + { "SOCKOPTFUNCTION", CURLOPT_SOCKOPTFUNCTION, CURLOT_FUNCTION, 0 }, + { "SOCKS5_AUTH", CURLOPT_SOCKS5_AUTH, CURLOT_LONG, 0 }, + { "SOCKS5_GSSAPI_NEC", CURLOPT_SOCKS5_GSSAPI_NEC, CURLOT_LONG, 0 }, + { "SOCKS5_GSSAPI_SERVICE", CURLOPT_SOCKS5_GSSAPI_SERVICE, + CURLOT_STRING, 0 }, + { "SSH_AUTH_TYPES", CURLOPT_SSH_AUTH_TYPES, CURLOT_VALUES, 0 }, + { "SSH_COMPRESSION", CURLOPT_SSH_COMPRESSION, CURLOT_LONG, 0 }, + { "SSH_HOSTKEYDATA", CURLOPT_SSH_HOSTKEYDATA, CURLOT_CBPTR, 0 }, + { "SSH_HOSTKEYFUNCTION", CURLOPT_SSH_HOSTKEYFUNCTION, CURLOT_FUNCTION, 0 }, + { "SSH_HOST_PUBLIC_KEY_MD5", CURLOPT_SSH_HOST_PUBLIC_KEY_MD5, + CURLOT_STRING, 0 }, + { "SSH_HOST_PUBLIC_KEY_SHA256", CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256, + CURLOT_STRING, 0 }, + { "SSH_KEYDATA", CURLOPT_SSH_KEYDATA, CURLOT_CBPTR, 0 }, + { "SSH_KEYFUNCTION", CURLOPT_SSH_KEYFUNCTION, CURLOT_FUNCTION, 0 }, + { "SSH_KNOWNHOSTS", CURLOPT_SSH_KNOWNHOSTS, CURLOT_STRING, 0 }, + { "SSH_PRIVATE_KEYFILE", CURLOPT_SSH_PRIVATE_KEYFILE, CURLOT_STRING, 0 }, + { "SSH_PUBLIC_KEYFILE", CURLOPT_SSH_PUBLIC_KEYFILE, CURLOT_STRING, 0 }, + { "SSLCERT", CURLOPT_SSLCERT, CURLOT_STRING, 0 }, + { "SSLCERTPASSWD", CURLOPT_KEYPASSWD, CURLOT_STRING, CURLOT_FLAG_ALIAS }, + { "SSLCERTTYPE", CURLOPT_SSLCERTTYPE, CURLOT_STRING, 0 }, + { "SSLCERT_BLOB", CURLOPT_SSLCERT_BLOB, CURLOT_BLOB, 0 }, + { "SSLENGINE", CURLOPT_SSLENGINE, CURLOT_STRING, 0 }, + { "SSLENGINE_DEFAULT", CURLOPT_SSLENGINE_DEFAULT, CURLOT_LONG, 0 }, + { "SSLKEY", CURLOPT_SSLKEY, CURLOT_STRING, 0 }, + { "SSLKEYPASSWD", CURLOPT_KEYPASSWD, CURLOT_STRING, CURLOT_FLAG_ALIAS }, + { "SSLKEYTYPE", CURLOPT_SSLKEYTYPE, CURLOT_STRING, 0 }, + { "SSLKEY_BLOB", CURLOPT_SSLKEY_BLOB, CURLOT_BLOB, 0 }, + { "SSLVERSION", CURLOPT_SSLVERSION, CURLOT_VALUES, 0 }, + { "SSL_CIPHER_LIST", CURLOPT_SSL_CIPHER_LIST, CURLOT_STRING, 0 }, + { "SSL_CTX_DATA", CURLOPT_SSL_CTX_DATA, CURLOT_CBPTR, 0 }, + { "SSL_CTX_FUNCTION", CURLOPT_SSL_CTX_FUNCTION, CURLOT_FUNCTION, 0 }, + { "SSL_EC_CURVES", CURLOPT_SSL_EC_CURVES, CURLOT_STRING, 0 }, + { "SSL_ENABLE_ALPN", CURLOPT_SSL_ENABLE_ALPN, CURLOT_LONG, 0 }, + { "SSL_ENABLE_NPN", CURLOPT_SSL_ENABLE_NPN, CURLOT_LONG, 0 }, + { "SSL_FALSESTART", CURLOPT_SSL_FALSESTART, CURLOT_LONG, 0 }, + { "SSL_OPTIONS", CURLOPT_SSL_OPTIONS, CURLOT_VALUES, 0 }, + { "SSL_SESSIONID_CACHE", CURLOPT_SSL_SESSIONID_CACHE, CURLOT_LONG, 0 }, + { "SSL_SIGNATURE_ALGORITHMS", CURLOPT_SSL_SIGNATURE_ALGORITHMS, + CURLOT_STRING, 0 }, + { "SSL_VERIFYHOST", CURLOPT_SSL_VERIFYHOST, CURLOT_LONG, 0 }, + { "SSL_VERIFYPEER", CURLOPT_SSL_VERIFYPEER, CURLOT_LONG, 0 }, + { "SSL_VERIFYSTATUS", CURLOPT_SSL_VERIFYSTATUS, CURLOT_LONG, 0 }, + { "STDERR", CURLOPT_STDERR, CURLOT_OBJECT, 0 }, + { "STREAM_DEPENDS", CURLOPT_STREAM_DEPENDS, CURLOT_OBJECT, 0 }, + { "STREAM_DEPENDS_E", CURLOPT_STREAM_DEPENDS_E, CURLOT_OBJECT, 0 }, + { "STREAM_WEIGHT", CURLOPT_STREAM_WEIGHT, CURLOT_LONG, 0 }, + { "SUPPRESS_CONNECT_HEADERS", CURLOPT_SUPPRESS_CONNECT_HEADERS, + CURLOT_LONG, 0 }, + { "TCP_FASTOPEN", CURLOPT_TCP_FASTOPEN, CURLOT_LONG, 0 }, + { "TCP_KEEPALIVE", CURLOPT_TCP_KEEPALIVE, CURLOT_LONG, 0 }, + { "TCP_KEEPCNT", CURLOPT_TCP_KEEPCNT, CURLOT_LONG, 0 }, + { "TCP_KEEPIDLE", CURLOPT_TCP_KEEPIDLE, CURLOT_LONG, 0 }, + { "TCP_KEEPINTVL", CURLOPT_TCP_KEEPINTVL, CURLOT_LONG, 0 }, + { "TCP_NODELAY", CURLOPT_TCP_NODELAY, CURLOT_LONG, 0 }, + { "TELNETOPTIONS", CURLOPT_TELNETOPTIONS, CURLOT_SLIST, 0 }, + { "TFTP_BLKSIZE", CURLOPT_TFTP_BLKSIZE, CURLOT_LONG, 0 }, + { "TFTP_NO_OPTIONS", CURLOPT_TFTP_NO_OPTIONS, CURLOT_LONG, 0 }, + { "TIMECONDITION", CURLOPT_TIMECONDITION, CURLOT_VALUES, 0 }, + { "TIMEOUT", CURLOPT_TIMEOUT, CURLOT_LONG, 0 }, + { "TIMEOUT_MS", CURLOPT_TIMEOUT_MS, CURLOT_LONG, 0 }, + { "TIMEVALUE", CURLOPT_TIMEVALUE, CURLOT_LONG, 0 }, + { "TIMEVALUE_LARGE", CURLOPT_TIMEVALUE_LARGE, CURLOT_OFF_T, 0 }, + { "TLS13_CIPHERS", CURLOPT_TLS13_CIPHERS, CURLOT_STRING, 0 }, + { "TLSAUTH_PASSWORD", CURLOPT_TLSAUTH_PASSWORD, CURLOT_STRING, 0 }, + { "TLSAUTH_TYPE", CURLOPT_TLSAUTH_TYPE, CURLOT_STRING, 0 }, + { "TLSAUTH_USERNAME", CURLOPT_TLSAUTH_USERNAME, CURLOT_STRING, 0 }, + { "TRAILERDATA", CURLOPT_TRAILERDATA, CURLOT_CBPTR, 0 }, + { "TRAILERFUNCTION", CURLOPT_TRAILERFUNCTION, CURLOT_FUNCTION, 0 }, + { "TRANSFERTEXT", CURLOPT_TRANSFERTEXT, CURLOT_LONG, 0 }, + { "TRANSFER_ENCODING", CURLOPT_TRANSFER_ENCODING, CURLOT_LONG, 0 }, + { "UNIX_SOCKET_PATH", CURLOPT_UNIX_SOCKET_PATH, CURLOT_STRING, 0 }, + { "UNRESTRICTED_AUTH", CURLOPT_UNRESTRICTED_AUTH, CURLOT_LONG, 0 }, + { "UPKEEP_INTERVAL_MS", CURLOPT_UPKEEP_INTERVAL_MS, CURLOT_LONG, 0 }, + { "UPLOAD", CURLOPT_UPLOAD, CURLOT_LONG, 0 }, + { "UPLOAD_BUFFERSIZE", CURLOPT_UPLOAD_BUFFERSIZE, CURLOT_LONG, 0 }, + { "UPLOAD_FLAGS", CURLOPT_UPLOAD_FLAGS, CURLOT_LONG, 0 }, + { "URL", CURLOPT_URL, CURLOT_STRING, 0 }, + { "USERAGENT", CURLOPT_USERAGENT, CURLOT_STRING, 0 }, + { "USERNAME", CURLOPT_USERNAME, CURLOT_STRING, 0 }, + { "USERPWD", CURLOPT_USERPWD, CURLOT_STRING, 0 }, + { "USE_SSL", CURLOPT_USE_SSL, CURLOT_VALUES, 0 }, + { "VERBOSE", CURLOPT_VERBOSE, CURLOT_LONG, 0 }, + { "WILDCARDMATCH", CURLOPT_WILDCARDMATCH, CURLOT_LONG, 0 }, + { "WRITEDATA", CURLOPT_WRITEDATA, CURLOT_CBPTR, 0 }, + { "WRITEFUNCTION", CURLOPT_WRITEFUNCTION, CURLOT_FUNCTION, 0 }, + { "WRITEHEADER", CURLOPT_HEADERDATA, CURLOT_CBPTR, CURLOT_FLAG_ALIAS }, + { "WS_OPTIONS", CURLOPT_WS_OPTIONS, CURLOT_LONG, 0 }, + { "XFERINFODATA", CURLOPT_XFERINFODATA, CURLOT_CBPTR, 0 }, + { "XFERINFOFUNCTION", CURLOPT_XFERINFOFUNCTION, CURLOT_FUNCTION, 0 }, + { "XOAUTH2_BEARER", CURLOPT_XOAUTH2_BEARER, CURLOT_STRING, 0 }, + { NULL, CURLOPT_LASTENTRY, CURLOT_LONG, 0 } /* end of table */ }; #ifdef DEBUGBUILD diff --git a/lib/easyoptions.h b/lib/easyoptions.h index 44b6a8280a8f..e908d15bed96 100644 --- a/lib/easyoptions.h +++ b/lib/easyoptions.h @@ -26,8 +26,6 @@ /* should probably go into the public header */ -#include - /* generated table with all easy options */ extern const struct curl_easyoption Curl_easyopts[]; diff --git a/lib/escape.c b/lib/escape.c index e7587e49b40e..2e38301d9ca5 100644 --- a/lib/escape.c +++ b/lib/escape.c @@ -23,25 +23,17 @@ ***************************************************************************/ /* Escape and unescape URL encoding in strings. The functions return a new - * allocated string or NULL if an error occurred. */ + * allocated string or NULL if an error occurred. */ #include "curl_setup.h" -#include - struct Curl_easy; #include "urldata.h" -#include "curlx/warnless.h" #include "escape.h" -#include "strdup.h" #include "curlx/strparse.h" #include "curl_printf.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - /* for ABI-compatibility with previous versions */ char *curl_escape(const char *string, int inlength) { @@ -57,8 +49,7 @@ char *curl_unescape(const char *string, int length) /* Escapes for URL the given unescaped string of given length. * 'data' is ignored since 7.82.0. */ -char *curl_easy_escape(CURL *data, const char *string, - int inlength) +char *curl_easy_escape(CURL *data, const char *string, int inlength) { size_t length; struct dynbuf d; @@ -69,7 +60,7 @@ char *curl_easy_escape(CURL *data, const char *string, length = (inlength ? (size_t)inlength : strlen(string)); if(!length) - return strdup(""); + return curlx_strdup(""); curlx_dyn_init(&d, length * 3 + 1); @@ -84,7 +75,7 @@ char *curl_easy_escape(CURL *data, const char *string, } else { /* encode it */ - unsigned char out[3]={'%'}; + unsigned char out[3] = { '%' }; Curl_hexbyte(&out[1], in); if(curlx_dyn_addn(&d, out, 3)) return NULL; @@ -121,7 +112,7 @@ CURLcode Curl_urldecode(const char *string, size_t length, DEBUGASSERT(ctrl >= REJECT_NADA); /* crash on TRUE/FALSE */ alloc = (length ? length : strlen(string)); - ns = malloc(alloc + 1); + ns = curlx_malloc(alloc + 1); if(!ns) return CURLE_OUT_OF_MEMORY; @@ -134,8 +125,8 @@ CURLcode Curl_urldecode(const char *string, size_t length, if(('%' == in) && (alloc > 2) && ISXDIGIT(string[1]) && ISXDIGIT(string[2])) { /* this is two hexadecimal digits following a '%' */ - in = (unsigned char)((Curl_hexval(string[1]) << 4) | - Curl_hexval(string[2])); + in = (unsigned char)((curlx_hexval(string[1]) << 4) | + curlx_hexval(string[2])); string += 3; alloc -= 3; } @@ -168,8 +159,7 @@ CURLcode Curl_urldecode(const char *string, size_t length, * If olen == NULL, no output length is stored. * 'data' is ignored since 7.82.0. */ -char *curl_easy_unescape(CURL *data, const char *string, - int length, int *olen) +char *curl_easy_unescape(CURL *data, const char *string, int length, int *olen) { char *str = NULL; (void)data; @@ -182,7 +172,7 @@ char *curl_easy_unescape(CURL *data, const char *string, return NULL; if(olen) { - if(outputlen <= (size_t) INT_MAX) + if(outputlen <= (size_t)INT_MAX) *olen = curlx_uztosi(outputlen); else /* too large to return in an int, fail! */ @@ -197,7 +187,7 @@ char *curl_easy_unescape(CURL *data, const char *string, the library's memory system */ void curl_free(void *p) { - free(p); + curlx_free(p); } /* diff --git a/lib/escape.h b/lib/escape.h index a43fc38ed321..2ea06c444fd3 100644 --- a/lib/escape.h +++ b/lib/escape.h @@ -26,8 +26,6 @@ /* Escape and unescape URL encoding in strings. The functions return a new * allocated string or NULL if an error occurred. */ -#include "curl_ctype.h" - enum urlreject { REJECT_NADA = 2, REJECT_CTRL, diff --git a/lib/fake_addrinfo.c b/lib/fake_addrinfo.c index 80edf7864857..d4173dbaa2e8 100644 --- a/lib/fake_addrinfo.c +++ b/lib/fake_addrinfo.c @@ -23,18 +23,13 @@ ***************************************************************************/ #include "curl_setup.h" + #include "fake_addrinfo.h" #ifdef USE_FAKE_GETADDRINFO -#include -#include #include -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - void r_freeaddrinfo(struct addrinfo *cahead) { struct addrinfo *canext; @@ -42,7 +37,7 @@ void r_freeaddrinfo(struct addrinfo *cahead) for(ca = cahead; ca; ca = canext) { canext = ca->ai_next; - free(ca); + curlx_free(ca); } } @@ -90,7 +85,7 @@ static struct addrinfo *mk_getaddrinfo(const struct ares_addrinfo *aihead) if((size_t)ai->ai_addrlen < ss_size) continue; - ca = malloc(sizeof(struct addrinfo) + ss_size + namelen); + ca = curlx_malloc(sizeof(struct addrinfo) + ss_size + namelen); if(!ca) { r_freeaddrinfo(cafirst); return NULL; @@ -180,13 +175,12 @@ int r_getaddrinfo(const char *node, curl_mfprintf(stderr, "ares_set_servers_ports_csv failed: %d", rc); /* Cleanup */ ares_destroy(channel); - return EAI_MEMORY; /* we can't run */ + return EAI_MEMORY; /* we cannot run */ } } } - ares_getaddrinfo(channel, node, service, &ahints, - async_addrinfo_cb, &ctx); + ares_getaddrinfo(channel, node, service, &ahints, async_addrinfo_cb, &ctx); /* Wait until no more requests are left to be processed */ ares_queue_wait_empty(channel, -1); diff --git a/lib/fake_addrinfo.h b/lib/fake_addrinfo.h index 13b0d71dba6d..4612aa02cb17 100644 --- a/lib/fake_addrinfo.h +++ b/lib/fake_addrinfo.h @@ -31,7 +31,7 @@ #endif #if defined(CURLDEBUG) && defined(USE_ARES) && defined(HAVE_GETADDRINFO) && \ - (ARES_VERSION >= 0x011a00) /* >= 1.26. 0 */ + (ARES_VERSION >= 0x011a00) /* >= 1.26.0 */ #define USE_FAKE_GETADDRINFO 1 #endif diff --git a/lib/file.c b/lib/file.c index fe07df5d2a92..a8617c213a29 100644 --- a/lib/file.c +++ b/lib/file.c @@ -55,25 +55,19 @@ #endif #include "urldata.h" -#include #include "progress.h" #include "sendf.h" +#include "curl_trc.h" #include "escape.h" #include "file.h" -#include "speedcheck.h" -#include "getinfo.h" #include "multiif.h" #include "transfer.h" #include "url.h" #include "parsedate.h" /* for the week day and month names */ #include "curlx/fopen.h" -#include "curlx/warnless.h" +#include "curlx/timeval.h" #include "curl_range.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - #if defined(_WIN32) || defined(MSDOS) #define DOS_FILESYSTEM 1 #elif defined(__amigaos4__) @@ -133,7 +127,6 @@ const struct Curl_handler Curl_handler_file = { PROTOPT_NONETWORK | PROTOPT_NOURLQUERY /* flags */ }; - static void file_cleanup(struct FILEPROTO *file) { Curl_safefree(file->freepath); @@ -150,7 +143,7 @@ static void file_easy_dtor(void *key, size_t klen, void *entry) (void)key; (void)klen; file_cleanup(file); - free(file); + curlx_free(file); } static CURLcode file_setup_connection(struct Curl_easy *data, @@ -159,7 +152,7 @@ static CURLcode file_setup_connection(struct Curl_easy *data, struct FILEPROTO *filep; (void)conn; /* allocate the FILE specific struct */ - filep = calloc(1, sizeof(*filep)); + filep = curlx_calloc(1, sizeof(*filep)); if(!filep || Curl_meta_set(data, CURL_META_FILE_EASY, filep, file_easy_dtor)) return CURLE_OUT_OF_MEMORY; @@ -271,12 +264,12 @@ static CURLcode file_connect(struct Curl_easy *data, bool *done) file->path = real_path; #endif #endif - free(file->freepath); + curlx_free(file->freepath); file->freepath = real_path; /* free this when done */ file->fd = fd; if(!data->state.upload && (fd == -1)) { - failf(data, "Couldn't open file %s", data->state.up.path); + failf(data, "Could not open file %s", data->state.up.path); file_done(data, CURLE_FILE_COULDNT_READ_FILE, FALSE); return CURLE_FILE_COULDNT_READ_FILE; } @@ -322,7 +315,6 @@ static CURLcode file_upload(struct Curl_easy *data, CURLcode result = CURLE_OK; char *xfer_ulbuf; size_t xfer_ulblen; - curl_off_t bytecount = 0; struct_stat file_stat; const char *sendbuf; bool eos = FALSE; @@ -338,13 +330,16 @@ static CURLcode file_upload(struct Curl_easy *data, if(!dir[1]) return CURLE_FILE_COULDNT_READ_FILE; /* fix: better error code */ - mode = O_WRONLY|O_CREAT|CURL_O_BINARY; + mode = O_WRONLY | O_CREAT | CURL_O_BINARY; if(data->state.resume_from) mode |= O_APPEND; else mode |= O_TRUNC; -#if (defined(ANDROID) || defined(__ANDROID__)) && \ +#ifdef _WIN32 + fd = curlx_open(file->path, mode, + data->set.new_file_perms & (_S_IREAD | _S_IWRITE)); +#elif (defined(ANDROID) || defined(__ANDROID__)) && \ (defined(__i386__) || defined(__arm__)) fd = curlx_open(file->path, mode, (mode_t)data->set.new_file_perms); #else @@ -374,8 +369,8 @@ static CURLcode file_upload(struct Curl_easy *data, goto out; while(!result && !eos) { - size_t nread; - ssize_t nwrite; + size_t nread, nwritten; + ssize_t rv; size_t readcount; result = Curl_client_read(data, xfer_ulbuf, xfer_ulblen, &readcount, &eos); @@ -404,23 +399,17 @@ static CURLcode file_upload(struct Curl_easy *data, sendbuf = xfer_ulbuf; /* write the data to the target */ - nwrite = write(fd, sendbuf, nread); - if((size_t)nwrite != nread) { + rv = write(fd, sendbuf, nread); + if(!curlx_sztouz(rv, &nwritten) || (nwritten != nread)) { result = CURLE_SEND_ERROR; break; } + Curl_pgrs_upload_inc(data, nwritten); - bytecount += nread; - - Curl_pgrsSetUploadCounter(data, bytecount); - - if(Curl_pgrsUpdate(data)) - result = CURLE_ABORTED_BY_CALLBACK; - else - result = Curl_speedcheck(data, curlx_now()); + result = Curl_pgrsCheck(data); } - if(!result && Curl_pgrsUpdate(data)) - result = CURLE_ABORTED_BY_CALLBACK; + if(!result) + result = Curl_pgrsUpdate(data); out: close(fd); @@ -485,7 +474,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done) const struct tm *tm = &buffer; char header[80]; int headerlen; - static const char accept_ranges[]= { "Accept-ranges: bytes\r\n" }; + static const char accept_ranges[] = { "Accept-ranges: bytes\r\n" }; if(expected_size >= 0) { headerlen = curl_msnprintf(header, sizeof(header), @@ -501,7 +490,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done) } filetime = (time_t)statbuf.st_mtime; - result = Curl_gmtime(filetime, &buffer); + result = curlx_gmtime(filetime, &buffer); if(result) return result; @@ -509,7 +498,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done) headerlen = curl_msnprintf(header, sizeof(header), "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n", - Curl_wkday[tm->tm_wday ? tm->tm_wday-1 : 6], + Curl_wkday[tm->tm_wday ? tm->tm_wday - 1 : 6], tm->tm_mday, Curl_month[tm->tm_mon], tm->tm_year + 1900, @@ -573,12 +562,12 @@ static CURLcode file_do(struct Curl_easy *data, bool *done) if(data->state.resume_from) { if(!S_ISDIR(statbuf.st_mode)) { -#if defined(__AMIGA__) || defined(__MINGW32CE__) +#ifdef __AMIGA__ if(data->state.resume_from != - lseek(fd, (off_t)data->state.resume_from, SEEK_SET)) + lseek(fd, (off_t)data->state.resume_from, SEEK_SET)) #else if(data->state.resume_from != - lseek(fd, data->state.resume_from, SEEK_SET)) + lseek(fd, data->state.resume_from, SEEK_SET)) #endif return CURLE_BAD_DOWNLOAD_RESUME; } @@ -598,11 +587,11 @@ static CURLcode file_do(struct Curl_easy *data, bool *done) size_t bytestoread; if(size_known) { - bytestoread = (expected_size < (curl_off_t)(xfer_blen-1)) ? - curlx_sotouz(expected_size) : (xfer_blen-1); + bytestoread = (expected_size < (curl_off_t)(xfer_blen - 1)) ? + curlx_sotouz(expected_size) : (xfer_blen - 1); } else - bytestoread = xfer_blen-1; + bytestoread = xfer_blen - 1; nread = read(fd, xfer_buf, bytestoread); @@ -619,10 +608,7 @@ static CURLcode file_do(struct Curl_easy *data, bool *done) if(result) goto out; - if(Curl_pgrsUpdate(data)) - result = CURLE_ABORTED_BY_CALLBACK; - else - result = Curl_speedcheck(data, curlx_now()); + result = Curl_pgrsCheck(data); if(result) goto out; } @@ -656,8 +642,8 @@ static CURLcode file_do(struct Curl_easy *data, bool *done) #endif } - if(Curl_pgrsUpdate(data)) - result = CURLE_ABORTED_BY_CALLBACK; + if(!result) + result = Curl_pgrsUpdate(data); out: Curl_multi_xfer_buf_release(data, xfer_buf); diff --git a/lib/fileinfo.c b/lib/fileinfo.c index 47cdb102e373..83d2ef0d005f 100644 --- a/lib/fileinfo.c +++ b/lib/fileinfo.c @@ -26,15 +26,11 @@ #ifndef CURL_DISABLE_FTP -#include "strdup.h" #include "fileinfo.h" -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" struct fileinfo *Curl_fileinfo_alloc(void) { - return calloc(1, sizeof(struct fileinfo)); + return curlx_calloc(1, sizeof(struct fileinfo)); } void Curl_fileinfo_cleanup(struct fileinfo *finfo) @@ -43,7 +39,7 @@ void Curl_fileinfo_cleanup(struct fileinfo *finfo) return; curlx_dyn_free(&finfo->buf); - free(finfo); + curlx_free(finfo); } #endif diff --git a/lib/fileinfo.h b/lib/fileinfo.h index 6746ee257552..a17b8d3426d0 100644 --- a/lib/fileinfo.h +++ b/lib/fileinfo.h @@ -24,7 +24,8 @@ * ***************************************************************************/ -#include +#include "curl_setup.h" + #include "llist.h" #include "curlx/dynbuf.h" diff --git a/lib/formdata.c b/lib/formdata.c index a98384c18ac9..576b64449661 100644 --- a/lib/formdata.c +++ b/lib/formdata.c @@ -24,33 +24,26 @@ #include "curl_setup.h" -#include - struct Curl_easy; #include "formdata.h" + #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_FORM_API) #include "urldata.h" /* for struct Curl_easy */ #include "mime.h" -#include "vtls/vtls.h" -#include "sendf.h" #include "strdup.h" -#include "rand.h" -#include "curlx/warnless.h" - -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" +#include "bufref.h" +#include "curlx/fopen.h" -#define HTTPPOST_PTRNAME CURL_HTTPPOST_PTRNAME -#define HTTPPOST_FILENAME CURL_HTTPPOST_FILENAME +#define HTTPPOST_PTRNAME CURL_HTTPPOST_PTRNAME +#define HTTPPOST_FILENAME CURL_HTTPPOST_FILENAME #define HTTPPOST_PTRCONTENTS CURL_HTTPPOST_PTRCONTENTS -#define HTTPPOST_READFILE CURL_HTTPPOST_READFILE -#define HTTPPOST_PTRBUFFER CURL_HTTPPOST_PTRBUFFER -#define HTTPPOST_CALLBACK CURL_HTTPPOST_CALLBACK -#define HTTPPOST_BUFFER CURL_HTTPPOST_BUFFER +#define HTTPPOST_READFILE CURL_HTTPPOST_READFILE +#define HTTPPOST_PTRBUFFER CURL_HTTPPOST_PTRBUFFER +#define HTTPPOST_CALLBACK CURL_HTTPPOST_CALLBACK +#define HTTPPOST_BUFFER CURL_HTTPPOST_BUFFER /*************************************************************************** * @@ -62,31 +55,30 @@ struct Curl_easy; * Returns newly allocated HttpPost on success and NULL if malloc failed. * ***************************************************************************/ -static struct curl_httppost * -AddHttpPost(struct FormInfo *src, - struct curl_httppost *parent_post, - struct curl_httppost **httppost, - struct curl_httppost **last_post) +static struct curl_httppost *AddHttpPost(struct FormInfo *src, + struct curl_httppost *parent_post, + struct curl_httppost **httppost, + struct curl_httppost **last_post) { struct curl_httppost *post; size_t namelength = src->namelength; - if(!namelength && src->name) - namelength = strlen(src->name); + if(!namelength && Curl_bufref_ptr(&src->name)) + namelength = strlen(Curl_bufref_ptr(&src->name)); if((src->bufferlength > LONG_MAX) || (namelength > LONG_MAX)) /* avoid overflow in typecasts below */ return NULL; - post = calloc(1, sizeof(struct curl_httppost)); + post = curlx_calloc(1, sizeof(struct curl_httppost)); if(post) { - post->name = src->name; + post->name = CURL_UNCONST(Curl_bufref_ptr(&src->name)); post->namelength = (long)namelength; - post->contents = src->value; + post->contents = CURL_UNCONST(Curl_bufref_ptr(&src->value)); post->contentlen = src->contentslength; post->buffer = src->buffer; post->bufferlength = (long)src->bufferlength; - post->contenttype = src->contenttype; + post->contenttype = CURL_UNCONST(Curl_bufref_ptr(&src->contenttype)); post->flags = src->flags | CURL_HTTPPOST_LARGE; post->contentheader = src->contentheader; - post->showfilename = src->showfilename; + post->showfilename = CURL_UNCONST(Curl_bufref_ptr(&src->showfilename)); post->userp = src->userp; } else @@ -111,60 +103,63 @@ AddHttpPost(struct FormInfo *src, return post; } +/* Allocate and initialize a new FormInfo structure. */ +static struct FormInfo *NewFormInfo(void) +{ + struct FormInfo *form_info = curlx_calloc(1, sizeof(struct FormInfo)); + + if(form_info) { + Curl_bufref_init(&form_info->name); + Curl_bufref_init(&form_info->value); + Curl_bufref_init(&form_info->contenttype); + Curl_bufref_init(&form_info->showfilename); + } + + return form_info; +} + +/* Replace the target field data by a dynamic copy of it. */ +static CURLcode FormInfoCopyField(struct bufref *field, size_t len) +{ + const char *value = Curl_bufref_ptr(field); + CURLcode result = CURLE_OK; + + if(value) { + if(!len) + len = strlen(value); + result = Curl_bufref_memdup0(field, value, len); + } + + return result; +} + /*************************************************************************** * * AddFormInfo() * - * Adds a FormInfo structure to the list presented by parent_form_info. - * - * Returns newly allocated FormInfo on success and NULL if malloc failed/ - * parent_form_info is NULL. + * Adds a FormInfo structure to the list presented by parent. * ***************************************************************************/ -static struct FormInfo *AddFormInfo(char *value, - char *contenttype, - struct FormInfo *parent_form_info) +static void AddFormInfo(struct FormInfo *form_info, struct FormInfo *parent) { - struct FormInfo *form_info; - form_info = calloc(1, sizeof(struct FormInfo)); - if(!form_info) - return NULL; - if(value) - form_info->value = value; - if(contenttype) - form_info->contenttype = contenttype; - form_info->flags = HTTPPOST_FILENAME; + form_info->flags |= HTTPPOST_FILENAME; - if(parent_form_info) { + if(parent) { /* now, point our 'more' to the original 'more' */ - form_info->more = parent_form_info->more; + form_info->more = parent->more; /* then move the original 'more' to point to ourselves */ - parent_form_info->more = form_info; + parent->more = form_info; } - - return form_info; } static void free_formlist(struct FormInfo *ptr) { for(; ptr != NULL; ptr = ptr->more) { - if(ptr->name_alloc) { - Curl_safefree(ptr->name); - ptr->name_alloc = FALSE; - } - if(ptr->value_alloc) { - Curl_safefree(ptr->value); - ptr->value_alloc = FALSE; - } - if(ptr->contenttype_alloc) { - Curl_safefree(ptr->contenttype); - ptr->contenttype_alloc = FALSE; - } - if(ptr->showfilename_alloc) { - Curl_safefree(ptr->showfilename); - ptr->showfilename_alloc = FALSE; - } + Curl_bufref_free(&ptr->name); + Curl_bufref_free(&ptr->value); + Curl_bufref_free(&ptr->contenttype); + Curl_bufref_free(&ptr->showfilename); } } @@ -230,82 +225,62 @@ static CURLFORMcode FormAddCheck(struct FormInfo *first_form, /* go through the list, check for completeness and if everything is * alright add the HttpPost item otherwise set retval accordingly */ - for(form = first_form; - form != NULL; - form = form->more) { - if(((!form->name || !form->value) && !post) || - ( (form->contentslength) && - (form->flags & HTTPPOST_FILENAME) ) || - ( (form->flags & HTTPPOST_FILENAME) && - (form->flags & HTTPPOST_PTRCONTENTS) ) || - - ( (!form->buffer) && - (form->flags & HTTPPOST_BUFFER) && - (form->flags & HTTPPOST_PTRBUFFER) ) || - - ( (form->flags & HTTPPOST_READFILE) && - (form->flags & HTTPPOST_PTRCONTENTS) ) + for(form = first_form; form != NULL; form = form->more) { + const char *name = Curl_bufref_ptr(&form->name); + + if(((!name || !Curl_bufref_ptr(&form->value)) && !post) || + (form->contentslength && + (form->flags & HTTPPOST_FILENAME)) || + ((form->flags & HTTPPOST_FILENAME) && + (form->flags & HTTPPOST_PTRCONTENTS)) || + + (!form->buffer && + (form->flags & HTTPPOST_BUFFER) && + (form->flags & HTTPPOST_PTRBUFFER)) || + + ((form->flags & HTTPPOST_READFILE) && + (form->flags & HTTPPOST_PTRCONTENTS)) ) { return CURL_FORMADD_INCOMPLETE; } if(((form->flags & HTTPPOST_FILENAME) || (form->flags & HTTPPOST_BUFFER)) && - !form->contenttype) { - char *f = (form->flags & HTTPPOST_BUFFER) ? - form->showfilename : form->value; - char const *type; - type = Curl_mime_contenttype(f); + !Curl_bufref_ptr(&form->contenttype)) { + const char *f = Curl_bufref_ptr((form->flags & HTTPPOST_BUFFER) ? + &form->showfilename : &form->value); + const char *type = Curl_mime_contenttype(f); if(!type) type = prevtype; if(!type) type = FILE_CONTENTTYPE_DEFAULT; /* our contenttype is missing */ - form->contenttype = strdup(type); - if(!form->contenttype) + if(Curl_bufref_memdup0(&form->contenttype, type, strlen(type))) return CURL_FORMADD_MEMORY; - - form->contenttype_alloc = TRUE; } - if(form->name && form->namelength) { - if(memchr(form->name, 0, form->namelength)) + if(name && form->namelength) { + if(memchr(name, 0, form->namelength)) return CURL_FORMADD_NULL; } - if(!(form->flags & HTTPPOST_PTRNAME) && form->name) { + if(!(form->flags & HTTPPOST_PTRNAME)) { /* Note that there is small risk that form->name is NULL here if the app passed in a bad combo, so we check for that. */ - - /* copy name (without strdup; possibly not null-terminated) */ - char *dupname = Curl_memdup0(form->name, form->namelength ? - form->namelength : strlen(form->name)); - if(!dupname) + if(FormInfoCopyField(&form->name, form->namelength)) return CURL_FORMADD_MEMORY; - - form->name = dupname; - form->name_alloc = TRUE; } if(!(form->flags & (HTTPPOST_FILENAME | HTTPPOST_READFILE | HTTPPOST_PTRCONTENTS | HTTPPOST_PTRBUFFER | - HTTPPOST_CALLBACK)) && form->value) { - /* copy value (without strdup; possibly contains null characters) */ - size_t clen = (size_t) form->contentslength; - if(!clen) - clen = strlen(form->value) + 1; - - form->value = Curl_memdup(form->value, clen); - - if(!form->value) + HTTPPOST_CALLBACK))) { + if(FormInfoCopyField(&form->value, (size_t)form->contentslength)) return CURL_FORMADD_MEMORY; - - form->value_alloc = TRUE; } post = AddHttpPost(form, post, httppost, last_post); if(!post) return CURL_FORMADD_MEMORY; - if(form->contenttype) - prevtype = form->contenttype; + if(Curl_bufref_ptr(&form->contenttype)) + prevtype = Curl_bufref_ptr(&form->contenttype); } return CURL_FORMADD_OK; @@ -319,15 +294,13 @@ static void free_chain(struct curl_httppost *c) struct curl_httppost *next = c->next; if(c->more) free_chain(c->more); - free(c); + curlx_free(c); c = next; } } -static -CURLFORMcode FormAdd(struct curl_httppost **httppost, - struct curl_httppost **last_post, - va_list params) +static CURLFORMcode FormAdd(struct curl_httppost **httppost, + struct curl_httppost **last_post, va_list params) { struct FormInfo *first_form, *curr, *form = NULL; CURLFORMcode retval = CURL_FORMADD_OK; @@ -337,15 +310,17 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, struct curl_httppost *newchain = NULL; struct curl_httppost *lastnode = NULL; - /* This is a state variable, that if TRUE means that we are parsing an - array that we got passed to us. If FALSE we are parsing the input - va_list arguments. */ - bool array_state = FALSE; +#define form_ptr_arg(t) (forms ? (t)(void *)avalue : va_arg(params, t)) +#ifdef HAVE_STDINT_H +#define form_int_arg(t) (forms ? (t)(uintptr_t)avalue : va_arg(params, t)) +#else +#define form_int_arg(t) (forms ? (t)(void *)avalue : va_arg(params, t)) +#endif /* * We need to allocate the first struct to fill in. */ - first_form = calloc(1, sizeof(struct FormInfo)); + first_form = NewFormInfo(); if(!first_form) return CURL_FORMADD_MEMORY; @@ -357,7 +332,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, while(retval == CURL_FORMADD_OK) { /* first see if we have more parts of the array param */ - if(array_state && forms) { + if(forms) { /* get the upcoming option from the given array */ option = forms->option; avalue = (char *)CURL_UNCONST(forms->value); @@ -365,7 +340,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, forms++; /* advance this to next entry */ if(CURLFORM_END == option) { /* end of array state */ - array_state = FALSE; + forms = NULL; continue; } } @@ -380,14 +355,12 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, switch(option) { case CURLFORM_ARRAY: - if(array_state) + if(forms) /* we do not support an array from within an array */ retval = CURL_FORMADD_ILLEGAL_ARRAY; else { forms = va_arg(params, struct curl_forms *); - if(forms) - array_state = TRUE; - else + if(!forms) retval = CURL_FORMADD_NULL; } break; @@ -396,17 +369,15 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, * Set the Name property. */ case CURLFORM_PTRNAME: - curr->flags |= HTTPPOST_PTRNAME; /* fall through */ - + curr->flags |= HTTPPOST_PTRNAME; FALLTHROUGH(); case CURLFORM_COPYNAME: - if(curr->name) + if(Curl_bufref_ptr(&curr->name)) retval = CURL_FORMADD_OPTION_TWICE; else { - if(!array_state) - avalue = va_arg(params, char *); + avalue = form_ptr_arg(char *); if(avalue) - curr->name = avalue; /* store for the moment */ + Curl_bufref_set(&curr->name, avalue, 0, NULL); /* No copy yet. */ else retval = CURL_FORMADD_NULL; } @@ -415,8 +386,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, if(curr->namelength) retval = CURL_FORMADD_OPTION_TWICE; else - curr->namelength = - array_state ? (size_t)avalue : (size_t)va_arg(params, long); + curr->namelength = (size_t)form_int_arg(long); break; /* @@ -426,44 +396,36 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, curr->flags |= HTTPPOST_PTRCONTENTS; FALLTHROUGH(); case CURLFORM_COPYCONTENTS: - if(curr->value) + if(Curl_bufref_ptr(&curr->value)) retval = CURL_FORMADD_OPTION_TWICE; else { - if(!array_state) - avalue = va_arg(params, char *); + avalue = form_ptr_arg(char *); if(avalue) - curr->value = avalue; /* store for the moment */ + Curl_bufref_set(&curr->value, avalue, 0, NULL); /* No copy yet. */ else retval = CURL_FORMADD_NULL; } break; case CURLFORM_CONTENTSLENGTH: - curr->contentslength = - array_state ? (size_t)avalue : (size_t)va_arg(params, long); + curr->contentslength = (curl_off_t)(size_t)form_int_arg(long); break; case CURLFORM_CONTENTLEN: curr->flags |= CURL_HTTPPOST_LARGE; - curr->contentslength = - array_state ? (curl_off_t)(size_t)avalue : - va_arg(params, curl_off_t); + curr->contentslength = form_int_arg(curl_off_t); break; /* Get contents from a given filename */ case CURLFORM_FILECONTENT: - if(curr->flags & (HTTPPOST_PTRCONTENTS|HTTPPOST_READFILE)) + if(curr->flags & (HTTPPOST_PTRCONTENTS | HTTPPOST_READFILE)) retval = CURL_FORMADD_OPTION_TWICE; else { - if(!array_state) - avalue = va_arg(params, char *); + avalue = form_ptr_arg(char *); if(avalue) { - curr->value = strdup(avalue); - if(!curr->value) + if(Curl_bufref_memdup0(&curr->value, avalue, strlen(avalue))) retval = CURL_FORMADD_MEMORY; - else { + else curr->flags |= HTTPPOST_READFILE; - curr->value_alloc = TRUE; - } } else retval = CURL_FORMADD_NULL; @@ -472,26 +434,20 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, /* We upload a file */ case CURLFORM_FILE: - if(!array_state) - avalue = va_arg(params, char *); - - if(curr->value) { + avalue = form_ptr_arg(char *); + if(Curl_bufref_ptr(&curr->value)) { if(curr->flags & HTTPPOST_FILENAME) { if(avalue) { - char *fname = strdup(avalue); - if(!fname) + form = NewFormInfo(); + if(!form || + Curl_bufref_memdup0(&form->value, avalue, strlen(avalue))) { + curlx_free(form); retval = CURL_FORMADD_MEMORY; + } else { - form = AddFormInfo(fname, NULL, curr); - if(!form) { - free(fname); - retval = CURL_FORMADD_MEMORY; - } - else { - form->value_alloc = TRUE; - curr = form; - form = NULL; - } + AddFormInfo(form, curr); + curr = form; + form = NULL; } } else @@ -502,13 +458,10 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, } else { if(avalue) { - curr->value = strdup(avalue); - if(!curr->value) + if(Curl_bufref_memdup0(&curr->value, avalue, strlen(avalue))) retval = CURL_FORMADD_MEMORY; - else { + else curr->flags |= HTTPPOST_FILENAME; - curr->value_alloc = TRUE; - } } else retval = CURL_FORMADD_NULL; @@ -516,16 +469,15 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, break; case CURLFORM_BUFFERPTR: - curr->flags |= HTTPPOST_PTRBUFFER|HTTPPOST_BUFFER; + curr->flags |= HTTPPOST_PTRBUFFER | HTTPPOST_BUFFER; if(curr->buffer) retval = CURL_FORMADD_OPTION_TWICE; else { - if(!array_state) - avalue = va_arg(params, char *); + avalue = form_ptr_arg(char *); if(avalue) { curr->buffer = avalue; /* store for the moment */ - curr->value = avalue; /* make it non-NULL to be accepted - as fine */ + /* Make value non-NULL to be accepted as fine */ + Curl_bufref_set(&curr->value, avalue, 0, NULL); } else retval = CURL_FORMADD_NULL; @@ -536,8 +488,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, if(curr->bufferlength) retval = CURL_FORMADD_OPTION_TWICE; else - curr->bufferlength = - array_state ? (size_t)avalue : (size_t)va_arg(params, long); + curr->bufferlength = (size_t)form_int_arg(long); break; case CURLFORM_STREAM: @@ -545,14 +496,13 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, if(curr->userp) retval = CURL_FORMADD_OPTION_TWICE; else { - if(!array_state) - avalue = va_arg(params, char *); + avalue = form_ptr_arg(char *); if(avalue) { curr->userp = avalue; - curr->value = avalue; /* this is not strictly true but we derive a - value from this later on and we need this - non-NULL to be accepted as a fine form - part */ + /* The following line is not strictly true but we derive a value + from this later on and we need this non-NULL to be accepted as + a fine form part */ + Curl_bufref_set(&curr->value, avalue, 0, NULL); } else retval = CURL_FORMADD_NULL; @@ -560,25 +510,20 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, break; case CURLFORM_CONTENTTYPE: - if(!array_state) - avalue = va_arg(params, char *); - if(curr->contenttype) { + avalue = form_ptr_arg(char *); + if(Curl_bufref_ptr(&curr->contenttype)) { if(curr->flags & HTTPPOST_FILENAME) { if(avalue) { - char *type = strdup(avalue); - if(!type) + form = NewFormInfo(); + if(!form || Curl_bufref_memdup0(&form->contenttype, avalue, + strlen(avalue))) { + curlx_free(form); retval = CURL_FORMADD_MEMORY; + } else { - form = AddFormInfo(NULL, type, curr); - if(!form) { - free(type); - retval = CURL_FORMADD_MEMORY; - } - else { - form->contenttype_alloc = TRUE; - curr = form; - form = NULL; - } + AddFormInfo(form, curr); + curr = form; + form = NULL; } } else @@ -587,47 +532,33 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, else retval = CURL_FORMADD_OPTION_TWICE; } - else { - if(avalue) { - curr->contenttype = strdup(avalue); - if(!curr->contenttype) - retval = CURL_FORMADD_MEMORY; - else - curr->contenttype_alloc = TRUE; - } - else - retval = CURL_FORMADD_NULL; + else if(avalue) { + if(Curl_bufref_memdup0(&curr->contenttype, avalue, strlen(avalue))) + retval = CURL_FORMADD_MEMORY; } + else + retval = CURL_FORMADD_NULL; break; - case CURLFORM_CONTENTHEADER: - { - /* this "cast increases required alignment of target type" but - we consider it OK anyway */ - struct curl_slist *list = array_state ? - (struct curl_slist *)(void *)avalue : - va_arg(params, struct curl_slist *); + case CURLFORM_CONTENTHEADER: { + /* this "cast increases required alignment of target type" but + we consider it OK anyway */ + struct curl_slist *list = form_ptr_arg(struct curl_slist *); - if(curr->contentheader) - retval = CURL_FORMADD_OPTION_TWICE; - else - curr->contentheader = list; + if(curr->contentheader) + retval = CURL_FORMADD_OPTION_TWICE; + else + curr->contentheader = list; - break; - } + break; + } case CURLFORM_FILENAME: case CURLFORM_BUFFER: - if(!array_state) - avalue = va_arg(params, char *); - if(curr->showfilename) + avalue = form_ptr_arg(char *); + if(Curl_bufref_ptr(&curr->showfilename)) retval = CURL_FORMADD_OPTION_TWICE; - else { - curr->showfilename = strdup(avalue); - if(!curr->showfilename) - retval = CURL_FORMADD_MEMORY; - else - curr->showfilename_alloc = TRUE; - } + else if(Curl_bufref_memdup0(&curr->showfilename, avalue, strlen(avalue))) + retval = CURL_FORMADD_MEMORY; break; default: @@ -649,7 +580,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, now by the httppost linked list */ while(first_form) { struct FormInfo *ptr = first_form->more; - free(first_form); + curlx_free(first_form); first_form = ptr; } @@ -666,6 +597,8 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, free_chain(newchain); return retval; +#undef form_ptr_arg +#undef form_int_arg } /* @@ -675,8 +608,7 @@ CURLFORMcode FormAdd(struct curl_httppost **httppost, */ CURLFORMcode curl_formadd(struct curl_httppost **httppost, - struct curl_httppost **last_post, - ...) + struct curl_httppost **last_post, ...) { va_list arg; CURLFORMcode result; @@ -699,6 +631,10 @@ int curl_formget(struct curl_httppost *form, void *arg, CURLcode result; curl_mimepart toppart; + /* Validate callback is provided */ + if(!append) + return (int)CURLE_BAD_FUNCTION_ARGUMENT; + Curl_mime_initpart(&toppart); /* default form is empty */ result = Curl_getformdata(NULL, &toppart, form, NULL); if(!result) @@ -720,7 +656,7 @@ int curl_formget(struct curl_httppost *form, void *arg, } Curl_mime_cleanpart(&toppart); - return (int) result; + return (int)result; } /* @@ -742,19 +678,17 @@ void curl_formfree(struct curl_httppost *form) curl_formfree(form->more); if(!(form->flags & HTTPPOST_PTRNAME)) - free(form->name); /* free the name */ + curlx_free(form->name); /* free the name */ if(!(form->flags & - (HTTPPOST_PTRCONTENTS|HTTPPOST_BUFFER|HTTPPOST_CALLBACK)) - ) - free(form->contents); /* free the contents */ - free(form->contenttype); /* free the content type */ - free(form->showfilename); /* free the faked filename */ - free(form); /* free the struct */ + (HTTPPOST_PTRCONTENTS | HTTPPOST_BUFFER | HTTPPOST_CALLBACK))) + curlx_free(form->contents); /* free the contents */ + curlx_free(form->contenttype); /* free the content type */ + curlx_free(form->showfilename); /* free the faked filename */ + curlx_free(form); /* free the struct */ form = next; } while(form); /* continue */ } - /* Set mime part name, taking care of non null-terminated name string. */ static CURLcode setname(curl_mimepart *part, const char *name, size_t len) { @@ -767,24 +701,10 @@ static CURLcode setname(curl_mimepart *part, const char *name, size_t len) if(!zname) return CURLE_OUT_OF_MEMORY; res = curl_mime_name(part, zname); - free(zname); + curlx_free(zname); return res; } -/* 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(_WIN32) && defined(USE_WIN32_LARGE_FILES) - return _fseeki64(stream, (__int64)offset, whence); -#elif defined(HAVE_FSEEKO) && defined(HAVE_DECL_FSEEKO) - return fseeko(stream, (off_t)offset, whence); -#else - if(offset > LONG_MAX) - return -1; - return fseek(stream, (long)offset, whence); -#endif -} - /* * Curl_getformdata() converts a linked list of "meta data" into a mime * structure. The input list is in 'post', while the output is stored in @@ -872,10 +792,10 @@ CURLcode Curl_getformdata(CURL *data, #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wcast-function-type-strict" #endif - result = curl_mime_data_cb(part, (curl_off_t) -1, - (curl_read_callback) fread, - fseeko_wrapper, - NULL, (void *) stdin); + result = curl_mime_data_cb(part, (curl_off_t)-1, + (curl_read_callback)fread, + curlx_fseek, + NULL, (void *)stdin); #if defined(__clang__) && __clang_major__ >= 16 #pragma clang diagnostic pop #endif @@ -910,7 +830,7 @@ CURLcode Curl_getformdata(CURL *data, /* Set fake filename. */ if(!result && post->showfilename) if(post->more || (post->flags & (HTTPPOST_FILENAME | HTTPPOST_BUFFER | - HTTPPOST_CALLBACK))) + HTTPPOST_CALLBACK))) result = curl_mime_filename(part, post->showfilename); } } @@ -924,8 +844,7 @@ CURLcode Curl_getformdata(CURL *data, #else /* if disabled */ CURLFORMcode curl_formadd(struct curl_httppost **httppost, - struct curl_httppost **last_post, - ...) + struct curl_httppost **last_post, ...) { (void)httppost; (void)last_post; @@ -947,4 +866,4 @@ void curl_formfree(struct curl_httppost *form) /* Nothing to do. */ } -#endif /* if disabled */ +#endif /* if disabled */ diff --git a/lib/formdata.h b/lib/formdata.h index 74f00bf4fcbc..4ece7d06e71e 100644 --- a/lib/formdata.h +++ b/lib/formdata.h @@ -28,25 +28,23 @@ #ifndef CURL_DISABLE_FORM_API +#include "bufref.h" + /* used by FormAdd for temporary storage */ struct FormInfo { - char *name; - size_t namelength; - char *value; - curl_off_t contentslength; - char *contenttype; + struct bufref name; + struct bufref value; + struct bufref contenttype; + struct bufref showfilename; /* The filename to show. If not set, the actual + filename will be used */ char *buffer; /* pointer to existing buffer used for file upload */ - size_t bufferlength; - char *showfilename; /* The filename to show. If not set, the actual - filename will be used */ char *userp; /* pointer for the read callback */ - struct curl_slist *contentheader; struct FormInfo *more; + struct curl_slist *contentheader; + curl_off_t contentslength; + size_t namelength; + size_t bufferlength; unsigned char flags; - BIT(name_alloc); - BIT(value_alloc); - BIT(contenttype_alloc); - BIT(showfilename_alloc); }; CURLcode Curl_getformdata(CURL *data, @@ -55,5 +53,4 @@ CURLcode Curl_getformdata(CURL *data, curl_read_callback fread_func); #endif /* CURL_DISABLE_FORM_API */ - #endif /* HEADER_CURL_FORMDATA_H */ diff --git a/lib/ftp.c b/lib/ftp.c index fd957a2bb485..a402dde5d8f4 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -40,9 +40,9 @@ #include #endif -#include #include "urldata.h" #include "sendf.h" +#include "curl_trc.h" #include "if2ip.h" #include "hostip.h" #include "progress.h" @@ -65,17 +65,11 @@ #include "sockaddr.h" /* required for Curl_sockaddr_storage */ #include "multiif.h" #include "url.h" -#include "speedcheck.h" -#include "curlx/warnless.h" #include "http_proxy.h" -#include "socks.h" #include "strdup.h" #include "curlx/strerr.h" #include "curlx/strparse.h" - -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" +#include "curlx/timeval.h" #ifndef NI_MAXHOST #define NI_MAXHOST 1025 @@ -86,18 +80,18 @@ /* macro to check for a three-digit ftp status code at the start of the given string */ -#define STATUSCODE(line) (ISDIGIT(line[0]) && ISDIGIT(line[1]) && \ - ISDIGIT(line[2])) +#define STATUSCODE(line) \ + (ISDIGIT(line[0]) && ISDIGIT(line[1]) && ISDIGIT(line[2])) /* macro to check for the last line in an FTP server response */ #define LASTLINE(line) (STATUSCODE(line) && (' ' == line[3])) #ifdef CURL_DISABLE_VERBOSE_STRINGS -#define ftp_pasv_verbose(a,b,c,d) Curl_nop_stmt -#define FTP_CSTATE(c) ((void)(c), "") +#define ftp_pasv_verbose(a, b, c, d) Curl_nop_stmt +#define FTP_CSTATE(c) ((void)(c), "") #else /* CURL_DISABLE_VERBOSE_STRINGS */ /* for tracing purposes */ -static const char * const ftp_state_names[]={ +static const char * const ftp_state_names[] = { "STOP", "WAIT220", "AUTH", @@ -136,7 +130,7 @@ static const char * const ftp_state_names[]={ "STOR", "QUIT" }; -#define FTP_CSTATE(ftpc) ((ftpc)? ftp_state_names[(ftpc)->state] : "???") +#define FTP_CSTATE(ftpc) ((ftpc) ? ftp_state_names[(ftpc)->state] : "???") #endif /* !CURL_DISABLE_VERBOSE_STRINGS */ @@ -168,12 +162,11 @@ static void ftp_state_low(struct Curl_easy *data, ftpc->state = newstate; } - /* Local API functions */ #ifndef DEBUGBUILD -#define ftp_state(x,y,z) ftp_state_low(x,y,z) +#define ftp_state(x, y, z) ftp_state_low(x, y, z) #else /* !DEBUGBUILD */ -#define ftp_state(x,y,z) ftp_state_low(x,y,z,__LINE__) +#define ftp_state(x, y, z) ftp_state_low(x, y, z, __LINE__) #endif /* DEBUGBUILD */ static CURLcode ftp_sendquote(struct Curl_easy *data, @@ -271,10 +264,10 @@ const struct Curl_handler Curl_handler_ftp = { CURLPROTO_FTP, /* family */ PROTOPT_DUAL | PROTOPT_CLOSEACTION | PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY | PROTOPT_PROXY_AS_HTTP | - PROTOPT_WILDCARD | PROTOPT_SSL_REUSE /* flags */ + PROTOPT_WILDCARD | PROTOPT_SSL_REUSE | + PROTOPT_CONN_REUSE /* flags */ }; - #ifdef USE_SSL /* * FTPS protocol handler. @@ -303,7 +296,8 @@ const struct Curl_handler Curl_handler_ftps = { CURLPROTO_FTPS, /* protocol */ CURLPROTO_FTP, /* family */ PROTOPT_SSL | PROTOPT_DUAL | PROTOPT_CLOSEACTION | - PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY | PROTOPT_WILDCARD /* flags */ + PROTOPT_NEEDSPWD | PROTOPT_NOURLQUERY | PROTOPT_WILDCARD | + PROTOPT_CONN_REUSE /* flags */ }; #endif @@ -316,25 +310,12 @@ static void close_secondarysocket(struct Curl_easy *data, Curl_conn_cf_discard_all(data, data->conn, SECONDARYSOCKET); } -/* - * NOTE: back in the old days, we added code in the FTP code that made NOBODY - * requests on files respond with headers passed to the client/stdout that - * looked like HTTP ones. - * - * This approach is not elegant, it causes confusion and is error-prone. It is - * subject for removal at the next (or at least a future) soname bump. Until - * then you can test the effects of the removal by undefining the following - * define named CURL_FTP_HTTPSTYLE_HEAD. - */ -#define CURL_FTP_HTTPSTYLE_HEAD 1 - static void freedirs(struct ftp_conn *ftpc) { Curl_safefree(ftpc->dirs); ftpc->dirdepth = 0; Curl_safefree(ftpc->rawpath); ftpc->file = NULL; - Curl_safefree(ftpc->newhost); } #ifdef CURL_PREFER_LF_LINEENDS @@ -430,7 +411,7 @@ static const struct Curl_cwtype ftp_cw_lc = { #endif /* CURL_PREFER_LF_LINEENDS */ -static CURLcode getftpresponse(struct Curl_easy *data, ssize_t *nread, +static CURLcode getftpresponse(struct Curl_easy *data, size_t *nread, int *ftpcode); /*********************************************************************** @@ -444,7 +425,7 @@ static CURLcode ftp_check_ctrl_on_data_wait(struct Curl_easy *data, struct connectdata *conn = data->conn; curl_socket_t ctrl_sock = conn->sock[FIRSTSOCKET]; struct pingpong *pp = &ftpc->pp; - ssize_t nread; + size_t nread; int ftpcode; bool response = FALSE; @@ -463,8 +444,7 @@ static CURLcode ftp_check_ctrl_on_data_wait(struct Curl_easy *data, /* there is pending control data still in the buffer to read */ response = TRUE; else { - int socketstate = Curl_socket_check(ctrl_sock, CURL_SOCKET_BAD, - CURL_SOCKET_BAD, 0); + int socketstate = SOCKET_READABLE(ctrl_sock, 0); /* see if the connection request is already here */ switch(socketstate) { case -1: /* error */ @@ -506,7 +486,7 @@ static CURLcode ftp_check_ctrl_on_data_wait(struct Curl_easy *data, infof(data, "FTP code: %03d", ftpcode); - if(ftpcode/100 > 3) + if(ftpcode / 100 > 3) return CURLE_FTP_ACCEPT_FAILED; return CURLE_WEIRD_SERVER_REPLY; @@ -534,7 +514,7 @@ static CURLcode ftp_initiate_transfer(struct Curl_easy *data, if(result || !connected) return result; - if(ftpc->state_saved == FTP_STOR) { + if(data->state.upload) { /* When we know we are uploading a specified file, we can get the file size prior to the actual upload. */ Curl_pgrsSetUploadSize(data, data->state.infilesize); @@ -549,7 +529,7 @@ static CURLcode ftp_initiate_transfer(struct Curl_easy *data, } else { /* FTP download, shutdown, do not ignore errors */ - Curl_xfer_setup_recv(data, SECONDARYSOCKET, ftpc->retr_size_saved); + Curl_xfer_setup_recv(data, SECONDARYSOCKET, data->req.size); Curl_xfer_set_shutdown(data, TRUE, FALSE); } @@ -615,7 +595,7 @@ static CURLcode ftp_readresp(struct Curl_easy *data, * */ static CURLcode getftpresponse(struct Curl_easy *data, - ssize_t *nreadp, /* return number of bytes + size_t *nreadp, /* return number of bytes read */ int *ftpcodep) /* return the ftp-code */ { @@ -688,8 +668,7 @@ static CURLcode getftpresponse(struct Curl_easy *data, return CURLE_RECV_ERROR; } else if(ev == 0) { - if(Curl_pgrsUpdate(data)) - return CURLE_ABORTED_BY_CALLBACK; + result = Curl_pgrsUpdate(data); continue; /* just continue in our loop for the timeout duration */ } } @@ -779,8 +758,8 @@ static CURLcode ftp_domore_pollset(struct Curl_easy *data, /* if stopped and still in this state, then we are also waiting for a connect on the secondary connection */ DEBUGASSERT(data->conn->sock[SECONDARYSOCKET] != CURL_SOCKET_BAD || - (data->conn->cfilter[SECONDARYSOCKET] && - !Curl_conn_is_connected(data->conn, SECONDARYSOCKET))); + (data->conn->cfilter[SECONDARYSOCKET] && + !Curl_conn_is_connected(data->conn, SECONDARYSOCKET))); /* An unconnected SECONDARY will add its socket by itself * via its adjust_pollset() */ return Curl_pollset_add_in(data, ps, data->conn->sock[FIRSTSOCKET]); @@ -799,7 +778,7 @@ static const char *pathpiece(struct ftp_conn *ftpc, int num) { DEBUGASSERT(ftpc->dirs); DEBUGASSERT(ftpc->dirdepth > num); - return &ftpc->rawpath[ ftpc->dirs[num].start ]; + return &ftpc->rawpath[ftpc->dirs[num].start]; } /* This is called after the FTP_QUOTE state is passed. @@ -970,7 +949,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data, if(addrlen) { const struct Curl_sockaddr_ex *remote_addr = - Curl_conn_get_remote_addr(data, FIRSTSOCKET); + Curl_conn_get_remote_addr(data, FIRSTSOCKET); DEBUGASSERT(remote_addr); if(!remote_addr) @@ -988,15 +967,15 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data, conn->scope_id, #endif ipstr, hbuf, sizeof(hbuf))) { - case IF2IP_NOT_FOUND: - /* not an interface, use the given string as hostname instead */ - host = ipstr; - break; - case IF2IP_AF_NOT_SUPPORTED: - goto out; - case IF2IP_FOUND: - host = hbuf; /* use the hbuf for hostname */ - break; + case IF2IP_NOT_FOUND: + /* not an interface, use the given string as hostname instead */ + host = ipstr; + break; + case IF2IP_AF_NOT_SUPPORTED: + goto out; + case IF2IP_FOUND: + host = hbuf; /* use the hbuf for hostname */ + break; } } else @@ -1077,7 +1056,7 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data, sa6->sin6_port = htons(port); #endif /* Try binding the given address. */ - if(bind(portsock, sa, sslen) ) { + if(bind(portsock, sa, sslen)) { /* It failed. */ error = SOCKERRNO; if(possibly_non_local && (error == SOCKEADDRNOTAVAIL)) { @@ -1116,7 +1095,6 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data, port++; } - /* get the name again after the bind() so that we can extract the port number it uses now */ sslen = sizeof(ss); @@ -1433,7 +1411,7 @@ static CURLcode ftp_state_list(struct Curl_easy *data, return CURLE_OUT_OF_MEMORY; result = Curl_pp_sendf(data, &ftpc->pp, "%s", cmd); - free(cmd); + curlx_free(cmd); if(!result) ftp_state(data, ftpc, FTP_LIST); @@ -1519,7 +1497,6 @@ static CURLcode ftp_state_mdtm(struct Curl_easy *data, return result; } - /* This is called after the TYPE and possible quote commands have been sent */ static CURLcode ftp_state_ul_setup(struct Curl_easy *data, struct ftp_conn *ftpc, @@ -1572,7 +1549,7 @@ static CURLcode ftp_state_ul_setup(struct Curl_easy *data, } /* seekerr == CURL_SEEKFUNC_CANTSEEK (cannot seek to offset) */ do { - char scratch[4*1024]; + char scratch[4 * 1024]; size_t readthisamountnow = (data->state.resume_from - passed > (curl_off_t)sizeof(scratch)) ? sizeof(scratch) : @@ -1770,12 +1747,11 @@ static CURLcode ftp_epsv_disable(struct Curl_easy *data, return result; } - -static char *control_address_dup(struct Curl_easy *data, - struct connectdata *conn) +static CURLcode ftp_control_addr_dup(struct Curl_easy *data, char **newhostp) { - struct ip_quadruple ipquad; - bool is_ipv6; + struct connectdata *conn = data->conn; + struct ip_quadruple ipquad; + bool is_ipv6; /* Returns the control connection IP address. If a proxy tunnel is used, returns the original hostname instead, because @@ -1783,11 +1759,19 @@ static char *control_address_dup(struct Curl_easy *data, not the ftp host. */ #ifndef CURL_DISABLE_PROXY if(conn->bits.tunnel_proxy || conn->bits.socksproxy) - return strdup(conn->host.name); + *newhostp = curlx_strdup(conn->host.name); + else #endif - if(!Curl_conn_get_ip_info(data, conn, FIRSTSOCKET, &is_ipv6, &ipquad)) - return strdup(ipquad.remote_ip); - return NULL; + if(!Curl_conn_get_ip_info(data, conn, FIRSTSOCKET, &is_ipv6, &ipquad) && + *ipquad.remote_ip) + *newhostp = curlx_strdup(ipquad.remote_ip); + else { + /* failed to get the remote_ip of the DATA connection */ + failf(data, "unable to get peername of DATA connection"); + *newhostp = NULL; + return CURLE_FTP_CANT_GET_HOST; + } + return *newhostp ? CURLE_OK : CURLE_OUT_OF_MEMORY; } static bool match_pasv_6nums(const char *p, @@ -1817,11 +1801,9 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data, struct Curl_dns_entry *dns = NULL; unsigned short connectport; /* the local port connect() should use! */ struct pingpong *pp = &ftpc->pp; - char *str = - curlx_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); + char *newhost = NULL; + unsigned short newport = 0; + char *str = curlx_dyn_ptr(&pp->recvbuf) + 4; /* start on the first letter */ if((ftpc->count1 == 0) && (ftpcode == 229)) { @@ -1839,10 +1821,10 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data, failf(data, "Illegal port number in EPSV reply"); return CURLE_FTP_WEIRD_PASV_REPLY; } - ftpc->newport = (unsigned short)num; - ftpc->newhost = control_address_dup(data, conn); - if(!ftpc->newhost) - return CURLE_OUT_OF_MEMORY; + newport = (unsigned short)num; + result = ftp_control_addr_dup(data, &newhost); + if(result) + return result; } else ptr = NULL; @@ -1873,7 +1855,7 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data, } if(!*str) { - failf(data, "Couldn't interpret the 227-response"); + failf(data, "Could not interpret the 227-response"); return CURLE_FTP_WEIRD_227_FORMAT; } @@ -1882,17 +1864,18 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data, /* told to ignore the remotely given IP but instead use the host we used for the control connection */ infof(data, "Skip %u.%u.%u.%u for data connection, reuse %s instead", - ip[0], ip[1], ip[2], ip[3], - conn->host.name); - ftpc->newhost = control_address_dup(data, conn); + ip[0], ip[1], ip[2], ip[3], conn->host.name); + result = ftp_control_addr_dup(data, &newhost); + if(result) + return result; } else - ftpc->newhost = curl_maprintf("%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); + newhost = curl_maprintf("%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]); - if(!ftpc->newhost) + if(!newhost) return CURLE_OUT_OF_MEMORY; - ftpc->newport = (unsigned short)(((ip[4] << 8) + ip[5]) & 0xffff); + newport = (unsigned short)(((ip[4] << 8) + ip[5]) & 0xffff); } else if(ftpc->count1 == 0) { /* EPSV failed, move on to PASV */ @@ -1906,7 +1889,7 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data, #ifndef CURL_DISABLE_PROXY if(conn->bits.proxy) { /* This connection uses a proxy and we need to connect to the proxy again - * here. We do not want to rely on a former host lookup that might've + * here. We do not want to rely on a former host lookup that might have * expired now, instead we remake the lookup here and now! */ struct ip_quadruple ipquad; bool is_ipv6; @@ -1916,7 +1899,7 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data, result = Curl_conn_get_ip_info(data, data->conn, FIRSTSOCKET, &is_ipv6, &ipquad); if(result) - return result; + goto error; (void)Curl_resolv_blocking(data, host_name, ipquad.remote_port, is_ipv6 ? CURL_IPRESOLVE_V6 : CURL_IPRESOLVE_V4, @@ -1926,31 +1909,31 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data, if(!dns) { failf(data, "cannot resolve proxy host %s:%hu", host_name, connectport); - return CURLE_COULDNT_RESOLVE_PROXY; + result = CURLE_COULDNT_RESOLVE_PROXY; + goto error; } } else #endif { /* normal, direct, ftp connection */ - DEBUGASSERT(ftpc->newhost); + DEBUGASSERT(newhost); /* postponed address resolution in case of tcp fastopen */ - if(conn->bits.tcp_fastopen && !conn->bits.reuse && !ftpc->newhost[0]) { - free(ftpc->newhost); - ftpc->newhost = control_address_dup(data, conn); - if(!ftpc->newhost) - return CURLE_OUT_OF_MEMORY; + if(conn->bits.tcp_fastopen && !conn->bits.reuse && !newhost[0]) { + curlx_free(newhost); + result = ftp_control_addr_dup(data, &newhost); + if(result) + goto error; } - (void)Curl_resolv_blocking(data, ftpc->newhost, ftpc->newport, - conn->ip_version, &dns); - connectport = ftpc->newport; /* we connect to the remote port */ + (void)Curl_resolv_blocking(data, newhost, newport, conn->ip_version, &dns); + connectport = newport; /* we connect to the remote port */ if(!dns) { - failf(data, "cannot resolve new host %s:%hu", - ftpc->newhost, connectport); - return CURLE_FTP_CANT_GET_HOST; + failf(data, "cannot resolve new host %s:%hu", newhost, connectport); + result = CURLE_FTP_CANT_GET_HOST; + goto error; } } @@ -1959,32 +1942,37 @@ static CURLcode ftp_state_pasv_resp(struct Curl_easy *data, CURL_CF_SSL_ENABLE : CURL_CF_SSL_DISABLE); if(result) { - if(ftpc->count1 == 0 && ftpcode == 229) + if(ftpc->count1 == 0 && ftpcode == 229) { + curlx_free(newhost); return ftp_epsv_disable(data, ftpc, conn); + } - return result; + goto error; } - /* - * When this is used from the multi interface, this might've returned with + * When this is used from the multi interface, this might have returned with * the 'connected' set to FALSE and thus we are now awaiting a non-blocking * connect to connect. */ if(data->set.verbose) /* this just dumps information about this second connection */ - ftp_pasv_verbose(data, dns->addr, ftpc->newhost, connectport); + ftp_pasv_verbose(data, dns->addr, newhost, connectport); - free(conn->secondaryhostname); - conn->secondary_port = ftpc->newport; - conn->secondaryhostname = strdup(ftpc->newhost); - if(!conn->secondaryhostname) - return CURLE_OUT_OF_MEMORY; + curlx_free(conn->secondaryhostname); + conn->secondary_port = newport; + conn->secondaryhostname = curlx_strdup(newhost); + if(!conn->secondaryhostname) { + result = CURLE_OUT_OF_MEMORY; + goto error; + } conn->bits.do_more = TRUE; ftp_state(data, ftpc, FTP_STOP); /* this phase is completed */ +error: + curlx_free(newhost); return result; } @@ -2027,7 +2015,7 @@ static CURLcode ftp_state_port_resp(struct Curl_easy *data, static int twodigit(const char *p) { - return (p[0]-'0') * 10 + (p[1]-'0'); + return (p[0] - '0') * 10 + (p[1] - '0'); } static bool ftp_213_date(const char *p, int *year, int *month, int *day, @@ -2082,28 +2070,26 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data, CURLcode result = CURLE_OK; switch(ftpcode) { - case 213: - { - /* 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; - struct pingpong *pp = &ftpc->pp; - char *resp = curlx_dyn_ptr(&pp->recvbuf) + 4; - bool showtime = FALSE; - if(ftp_213_date(resp, &year, &month, &day, &hour, &minute, &second)) { - /* we have a time, reformat it */ - char timebuf[24]; - curl_msnprintf(timebuf, sizeof(timebuf), - "%04d%02d%02d %02d:%02d:%02d GMT", - year, month, day, hour, minute, second); - /* now, convert this into a time() value: */ - if(!Curl_getdate_capped(timebuf, &data->info.filetime)) - showtime = TRUE; - } + case 213: { + /* 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; + struct pingpong *pp = &ftpc->pp; + char *resp = curlx_dyn_ptr(&pp->recvbuf) + 4; + bool showtime = FALSE; + if(ftp_213_date(resp, &year, &month, &day, &hour, &minute, &second)) { + /* we have a time, reformat it */ + char timebuf[24]; + curl_msnprintf(timebuf, sizeof(timebuf), + "%04d%02d%02d %02d:%02d:%02d GMT", + year, month, day, hour, minute, second); + /* now, convert this into a time() value: */ + if(!Curl_getdate_capped(timebuf, &data->info.filetime)) + showtime = TRUE; + } -#ifdef CURL_FTP_HTTPSTYLE_HEAD - /* If we asked for a time of the file and we actually got one as well, - we "emulate" an HTTP-style header in our output. */ + /* If we asked for a time of the file and we actually got one as well, + we "emulate" an HTTP-style header in our output. */ #if defined(__GNUC__) && (defined(__DJGPP__) || defined(__AMIGA__)) #pragma GCC diagnostic push @@ -2111,39 +2097,38 @@ static CURLcode ftp_state_mdtm_resp(struct Curl_easy *data, warning: comparison of unsigned expression in '>= 0' is always true */ #pragma GCC diagnostic ignored "-Wtype-limits" #endif - if(data->req.no_body && ftpc->file && - data->set.get_filetime && showtime) { + if(data->req.no_body && ftpc->file && + data->set.get_filetime && showtime) { #if defined(__GNUC__) && (defined(__DJGPP__) || defined(__AMIGA__)) #pragma GCC diagnostic pop #endif - char headerbuf[128]; - int headerbuflen; - time_t filetime = data->info.filetime; - struct tm buffer; - const struct tm *tm = &buffer; + char headerbuf[128]; + int headerbuflen; + time_t filetime = data->info.filetime; + struct tm buffer; + const struct tm *tm = &buffer; - result = Curl_gmtime(filetime, &buffer); - if(result) - return result; + result = curlx_gmtime(filetime, &buffer); + if(result) + return result; - /* format: "Tue, 15 Nov 1994 12:45:26" */ - headerbuflen = - curl_msnprintf(headerbuf, sizeof(headerbuf), - "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d " - "GMT\r\n", - Curl_wkday[tm->tm_wday ? tm->tm_wday-1 : 6], - tm->tm_mday, - Curl_month[tm->tm_mon], - tm->tm_year + 1900, - tm->tm_hour, - tm->tm_min, - tm->tm_sec); - result = client_write_header(data, headerbuf, headerbuflen); - if(result) - return result; - } /* end of a ridiculous amount of conditionals */ -#endif - } + /* format: "Tue, 15 Nov 1994 12:45:26" */ + headerbuflen = + curl_msnprintf(headerbuf, sizeof(headerbuf), + "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d " + "GMT\r\n", + Curl_wkday[tm->tm_wday ? tm->tm_wday-1 : 6], + tm->tm_mday, + Curl_month[tm->tm_mon], + tm->tm_year + 1900, + tm->tm_hour, + tm->tm_min, + tm->tm_sec); + result = client_write_header(data, headerbuf, headerbuflen); + if(result) + return result; + } /* end of a ridiculous amount of conditionals */ + } break; default: infof(data, "unsupported MDTM reply format"); @@ -2199,11 +2184,11 @@ static CURLcode ftp_state_type_resp(struct Curl_easy *data, { CURLcode result = CURLE_OK; - if(ftpcode/100 != 2) { + if(ftpcode / 100 != 2) { /* "sasserftpd" and "(u)r(x)bot ftpd" both responds with 226 after a successful 'TYPE I'. While that is not as RFC959 says, it is still a positive response code and we allow that. */ - failf(data, "Couldn't set desired mode"); + failf(data, "Could not set desired mode"); return CURLE_FTP_COULDNT_SET_TYPE; } if(ftpcode != 200) @@ -2272,7 +2257,7 @@ static CURLcode ftp_state_retr(struct Curl_easy *data, return CURLE_BAD_DOWNLOAD_RESUME; } /* Now store the number of bytes we are expected to download */ - ftp->downloadsize = filesize-data->state.resume_from; + ftp->downloadsize = filesize - data->state.resume_from; } } @@ -2347,7 +2332,6 @@ static CURLcode ftp_state_size_resp(struct Curl_easy *data, } if(instate == FTP_SIZE) { -#ifdef CURL_FTP_HTTPSTYLE_HEAD if(filesize != -1) { char clbuf[128]; int clbuflen = curl_msnprintf(clbuf, sizeof(clbuf), @@ -2357,7 +2341,6 @@ static CURLcode ftp_state_size_resp(struct Curl_easy *data, if(result) return result; } -#endif Curl_pgrsSetDownloadSize(data, filesize); result = ftp_state_rest(data, ftpc, ftp); } @@ -2384,20 +2367,18 @@ static CURLcode ftp_state_rest_resp(struct Curl_easy *data, switch(instate) { case FTP_REST: default: -#ifdef CURL_FTP_HTTPSTYLE_HEAD if(ftpcode == 350) { - char buffer[24]= { "Accept-ranges: bytes\r\n" }; + char buffer[24] = { "Accept-ranges: bytes\r\n" }; result = client_write_header(data, buffer, strlen(buffer)); if(result) return result; } -#endif result = ftp_state_prepare_transfer(data, ftpc, ftp); break; case FTP_RETR_REST: if(ftpcode != 350) { - failf(data, "Couldn't use REST"); + failf(data, "Could not use REST"); result = CURLE_FTP_COULDNT_USE_REST; } else { @@ -2413,7 +2394,7 @@ static CURLcode ftp_state_rest_resp(struct Curl_easy *data, static CURLcode ftp_state_stor_resp(struct Curl_easy *data, struct ftp_conn *ftpc, - int ftpcode, ftpstate instate) + int ftpcode) { CURLcode result = CURLE_OK; @@ -2423,8 +2404,6 @@ static CURLcode ftp_state_stor_resp(struct Curl_easy *data, return CURLE_UPLOAD_FAILED; } - ftpc->state_saved = instate; - /* PORT means we are now awaiting the server to connect to us. */ if(data->set.ftp_use_port) { bool connected; @@ -2473,8 +2452,7 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data, E: 125 Data connection already open; Transfer starting. */ - curl_off_t size = -1; /* default unknown size */ - + data->req.size = -1; /* default unknown size */ /* * It appears that there are FTP-servers that return size 0 for files when @@ -2506,28 +2484,25 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data, if(!curlx_str_number(&c, &what, CURL_OFF_T_MAX) && !curlx_str_single(&c, ' ') && !strncmp(c, "bytes", 5)) { - size = what; + data->req.size = what; break; } } } } else if(ftp->downloadsize > -1) - size = ftp->downloadsize; + data->req.size = ftp->downloadsize; - if(size > data->req.maxdownload && data->req.maxdownload > 0) - size = data->req.size = data->req.maxdownload; + if(data->req.size > data->req.maxdownload && data->req.maxdownload > 0) + data->req.size = data->req.maxdownload; else if((instate != FTP_LIST) && (data->state.prefer_ascii)) - size = -1; /* kludge for servers that understate ASCII mode file size */ + data->req.size = -1; /* for servers that understate ASCII mode file + size */ infof(data, "Maxdownload = %" FMT_OFF_T, data->req.maxdownload); if(instate != FTP_LIST) - infof(data, "Getting file with size: %" FMT_OFF_T, size); - - /* FTP download: */ - ftpc->state_saved = instate; - ftpc->retr_size_saved = size; + infof(data, "Getting file with size: %" FMT_OFF_T, data->req.size); if(data->set.ftp_use_port) { bool connected; @@ -2548,7 +2523,7 @@ static CURLcode ftp_state_get_resp(struct Curl_easy *data, } else { if((instate == FTP_LIST) && (ftpcode == 450)) { - /* simply no matching files in the dir listing */ + /* simply no matching files in the directory listing */ ftp->transfer = PPTRANSFER_NONE; /* do not download anything */ ftp_state(data, ftpc, FTP_STOP); /* this phase is over */ } @@ -2605,12 +2580,11 @@ static CURLcode ftp_state_user_resp(struct Curl_easy *data, if((ftpcode == 331) && (ftpc->state == FTP_USER)) { /* 331 Password required for ... (the server requires to send the user's password too) */ - result = Curl_pp_sendf(data, &ftpc->pp, "PASS %s", - data->conn->passwd); + result = Curl_pp_sendf(data, &ftpc->pp, "PASS %s", data->conn->passwd); if(!result) ftp_state(data, ftpc, FTP_PASS); } - else if(ftpcode/100 == 2) { + else if(ftpcode / 100 == 2) { /* 230 User ... logged in. (the user logged in with or without password) */ result = ftp_state_loggedin(data, ftpc); @@ -2636,9 +2610,8 @@ static CURLcode ftp_state_user_resp(struct Curl_easy *data, if(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER] && !ftpc->ftp_trying_alternative) { /* Ok, USER failed. Let's try the supplied command. */ - result = - Curl_pp_sendf(data, &ftpc->pp, "%s", - data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]); + result = Curl_pp_sendf(data, &ftpc->pp, "%s", + data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]); if(!result) { ftpc->ftp_trying_alternative = TRUE; ftp_state(data, ftpc, FTP_USER); @@ -2734,29 +2707,24 @@ static CURLcode ftp_pwd_resp(struct Curl_easy *data, if(!ftpc->server_os && dir[0] != '/') { result = Curl_pp_sendf(data, &ftpc->pp, "%s", "SYST"); if(result) { - free(dir); + curlx_free(dir); return result; } - free(ftpc->entrypath); - ftpc->entrypath = dir; /* remember this */ - infof(data, "Entry path is '%s'", ftpc->entrypath); - /* also save it where getinfo can access it: */ - free(data->state.most_recent_ftp_entrypath); - data->state.most_recent_ftp_entrypath = strdup(ftpc->entrypath); - if(!data->state.most_recent_ftp_entrypath) - return CURLE_OUT_OF_MEMORY; - ftp_state(data, ftpc, FTP_SYST); - return result; } - free(ftpc->entrypath); + curlx_free(ftpc->entrypath); ftpc->entrypath = dir; /* remember this */ infof(data, "Entry path is '%s'", ftpc->entrypath); /* also save it where getinfo can access it: */ - free(data->state.most_recent_ftp_entrypath); - data->state.most_recent_ftp_entrypath = strdup(ftpc->entrypath); + curlx_free(data->state.most_recent_ftp_entrypath); + data->state.most_recent_ftp_entrypath = curlx_strdup(ftpc->entrypath); if(!data->state.most_recent_ftp_entrypath) return CURLE_OUT_OF_MEMORY; + + if(!ftpc->server_os && dir[0] != '/') { + ftp_state(data, ftpc, FTP_SYST); + return CURLE_OK; + } } else { /* could not get the path */ @@ -2809,8 +2777,7 @@ static CURLcode ftp_wait_resp(struct Curl_easy *data, (int)data->set.ftpsslauth); return CURLE_UNKNOWN_OPTION; /* we do not know what to do */ } - result = Curl_pp_sendf(data, &ftpc->pp, "AUTH %s", - ftpauth[ftpc->count1]); + result = Curl_pp_sendf(data, &ftpc->pp, "AUTH %s", ftpauth[ftpc->count1]); if(!result) ftp_state(data, ftpc, FTP_AUTH); } @@ -2910,10 +2877,9 @@ static CURLcode ftp_pp_statemachine(struct Curl_easy *data, break; case FTP_PROT: - if(ftpcode/100 == 2) + if(ftpcode / 100 == 2) /* We have enabled SSL for the data connection! */ - conn->bits.ftp_use_data_ssl = - (data->set.use_ssl != CURLUSESSL_CONTROL); + conn->bits.ftp_use_data_ssl = (data->set.use_ssl != CURLUSESSL_CONTROL); /* FTP servers typically responds with 500 if they decide to reject our 'P' request */ else if(data->set.use_ssl > CURLUSESSL_CONTROL) @@ -2977,18 +2943,18 @@ static CURLcode ftp_pp_statemachine(struct Curl_easy *data, /* Force OS400 name format 1. */ result = Curl_pp_sendf(data, &ftpc->pp, "%s", "SITE NAMEFMT 1"); if(result) { - free(os); + curlx_free(os); return result; } /* remember target server OS */ - free(ftpc->server_os); + curlx_free(ftpc->server_os); ftpc->server_os = os; ftp_state(data, ftpc, FTP_NAMEFMT); break; } /* Nothing special for the target server. */ /* remember target server OS */ - free(ftpc->server_os); + curlx_free(ftpc->server_os); ftpc->server_os = os; } else { @@ -3025,7 +2991,7 @@ static CURLcode ftp_pp_statemachine(struct Curl_easy *data, break; case FTP_CWD: - if(ftpcode/100 != 2) { + if(ftpcode / 100 != 2) { /* failure to CWD there */ if(data->set.ftp_create_missing_dirs && ftpc->cwdcount && !ftpc->count2) { @@ -3067,8 +3033,8 @@ static CURLcode ftp_pp_statemachine(struct Curl_easy *data, break; case FTP_MKD: - if((ftpcode/100 != 2) && !ftpc->count3--) { - /* failure to MKD the dir */ + if((ftpcode / 100 != 2) && !ftpc->count3--) { + /* failure to MKD the directory */ failf(data, "Failed to MKD dir: %03d", ftpcode); result = CURLE_REMOTE_ACCESS_DENIED; } @@ -3127,7 +3093,7 @@ static CURLcode ftp_pp_statemachine(struct Curl_easy *data, break; case FTP_STOR: - result = ftp_state_stor_resp(data, ftpc, ftpcode, ftpc->state); + result = ftp_state_stor_resp(data, ftpc, ftpcode); break; case FTP_QUIT: @@ -3140,7 +3106,6 @@ static CURLcode ftp_pp_statemachine(struct Curl_easy *data, return result; } - /* called repeatedly until done from multi.c */ static CURLcode ftp_statemach(struct Curl_easy *data, struct ftp_conn *ftpc, @@ -3201,9 +3166,6 @@ static CURLcode ftp_connect(struct Curl_easy *data, if(!ftpc) return CURLE_FAILED_INIT; pp = &ftpc->pp; - /* We always support persistent connections on ftp */ - connkeep(conn, "FTP default"); - PINGPONG_SETUP(pp, ftp_pp_statemachine, ftp_endofresp); if(Curl_conn_is_ssl(conn, FIRSTSOCKET)) { @@ -3214,7 +3176,7 @@ static CURLcode ftp_connect(struct Curl_easy *data, conn->bits.ftp_use_control_ssl = TRUE; } - Curl_pp_init(pp); /* once per transfer */ + Curl_pp_init(pp, Curl_pgrs_now(data)); /* once per transfer */ /* When we connect, we start in the state where we await the 220 response */ @@ -3241,7 +3203,7 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status, struct FTP *ftp = Curl_meta_get(data, CURL_META_FTP_EASY); struct ftp_conn *ftpc = Curl_conn_meta_get(data->conn, CURL_META_FTP_CONN); struct pingpong *pp; - ssize_t nread; + size_t nread; int ftpcode; CURLcode result = CURLE_OK; @@ -3296,7 +3258,7 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status, * the error path) */ ftpc->ctl_valid = FALSE; /* mark control connection as bad */ connclose(conn, "FTP: out of memory!"); /* mark for connection closure */ - free(ftpc->prevpath); + curlx_free(ftpc->prevpath); ftpc->prevpath = NULL; /* no path remembering */ } else { /* remember working directory for connection reuse */ @@ -3307,7 +3269,7 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status, else { size_t pathLen = strlen(ftpc->rawpath); - free(ftpc->prevpath); + curlx_free(ftpc->prevpath); if(!ftpc->cwdfail) { if(data->set.ftp_filemethod == FTPFILE_NOCWD) @@ -3322,15 +3284,11 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status, } } if(ftpc->prevpath) - infof(data, "Remembering we are in dir \"%s\"", ftpc->prevpath); + infof(data, "Remembering we are in directory \"%s\"", ftpc->prevpath); } /* shut down the socket to inform the server we are done */ -#ifdef UNDER_CE - shutdown(conn->sock[SECONDARYSOCKET], 2); /* SD_BOTH */ -#endif - if(Curl_conn_is_setup(conn, SECONDARYSOCKET)) { if(!result && ftpc->dont_check && data->req.maxdownload > 0) { /* partial download completed */ @@ -3354,15 +3312,9 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status, * data has been transferred. This happens when doing through NATs etc that * abandon old silent connections. */ - timediff_t old_time = pp->response_time; - - pp->response_time = 60*1000; /* give it only a minute for now */ - pp->response = curlx_now(); /* timeout relative now */ - + pp->response = *Curl_pgrs_now(data); /* timeout relative now */ result = getftpresponse(data, &nread, &ftpcode); - pp->response_time = old_time; /* set this back to previous value */ - if(!nread && (CURLE_OPERATION_TIMEDOUT == result)) { failf(data, "control connection looks dead"); ftpc->ctl_valid = FALSE; /* mark control connection as bad */ @@ -3452,10 +3404,9 @@ static CURLcode ftp_done(struct Curl_easy *data, CURLcode status, * * BLOCKING */ -static -CURLcode ftp_sendquote(struct Curl_easy *data, - struct ftp_conn *ftpc, - struct curl_slist *quote) +static CURLcode ftp_sendquote(struct Curl_easy *data, + struct ftp_conn *ftpc, + struct curl_slist *quote) { struct curl_slist *item; struct pingpong *pp = &ftpc->pp; @@ -3463,7 +3414,7 @@ CURLcode ftp_sendquote(struct Curl_easy *data, item = quote; while(item) { if(item->data) { - ssize_t nread; + size_t nread; char *cmd = item->data; bool acceptfail = FALSE; CURLcode result; @@ -3481,7 +3432,7 @@ CURLcode ftp_sendquote(struct Curl_easy *data, result = Curl_pp_sendf(data, &ftpc->pp, "%s", cmd); if(!result) { - pp->response = curlx_now(); /* timeout relative now */ + pp->response = *Curl_pgrs_now(data); /* timeout relative now */ result = getftpresponse(data, &nread, &ftpcode); } if(result) @@ -3731,7 +3682,6 @@ static CURLcode ftp_do_more(struct Curl_easy *data, int *completep) return result; } - /*********************************************************************** * * ftp_perform() @@ -3786,7 +3736,7 @@ static void wc_data_dtor(void *ptr) struct ftp_wc *ftpwc = ptr; if(ftpwc && ftpwc->parser) Curl_ftp_parselist_data_free(&ftpwc->parser); - free(ftpwc); + curlx_free(ftpwc); } static CURLcode init_wc_data(struct Curl_easy *data, @@ -3806,14 +3756,14 @@ static CURLcode init_wc_data(struct Curl_easy *data, wildcard->state = CURLWC_CLEAN; return ftp_parse_url_path(data, ftpc, ftp); } - wildcard->pattern = strdup(last_slash); + wildcard->pattern = curlx_strdup(last_slash); if(!wildcard->pattern) return CURLE_OUT_OF_MEMORY; last_slash[0] = '\0'; /* cut file from path */ } else { /* there is only 'wildcard pattern' or nothing */ if(path[0]) { - wildcard->pattern = strdup(path); + wildcard->pattern = curlx_strdup(path); if(!wildcard->pattern) return CURLE_OUT_OF_MEMORY; path[0] = '\0'; @@ -3828,7 +3778,7 @@ static CURLcode init_wc_data(struct Curl_easy *data, resources for wildcard transfer */ /* allocate ftp protocol specific wildcard data */ - ftpwc = calloc(1, sizeof(struct ftp_wc)); + ftpwc = curlx_calloc(1, sizeof(struct ftp_wc)); if(!ftpwc) { result = CURLE_OUT_OF_MEMORY; goto fail; @@ -3854,7 +3804,7 @@ static CURLcode init_wc_data(struct Curl_easy *data, goto fail; } - wildcard->path = strdup(ftp->path); + wildcard->path = curlx_strdup(ftp->path); if(!wildcard->path) { result = CURLE_OUT_OF_MEMORY; goto fail; @@ -3875,7 +3825,7 @@ static CURLcode init_wc_data(struct Curl_easy *data, fail: if(ftpwc) { Curl_ftp_parselist_data_free(&ftpwc->parser); - free(ftpwc); + curlx_free(ftpwc); } Curl_safefree(wildcard->pattern); wildcard->dtor = ZERO_NULL; @@ -3933,7 +3883,7 @@ static CURLcode wc_statemach(struct Curl_easy *data, return CURLE_OUT_OF_MEMORY; /* switch default ftp->path and tmp_path */ - free(ftp->pathalloc); + curlx_free(ftp->pathalloc); ftp->pathalloc = ftp->path = tmp_path; infof(data, "Wildcard - START of \"%s\"", finfo->filename); @@ -3946,8 +3896,7 @@ static CURLcode wc_statemach(struct Curl_easy *data, Curl_set_in_callback(data, FALSE); switch(userresponse) { case CURL_CHUNK_BGN_FUNC_SKIP: - infof(data, "Wildcard - \"%s\" skipped by user", - finfo->filename); + infof(data, "Wildcard - \"%s\" skipped by user", finfo->filename); wildcard->state = CURLWC_SKIP; continue; case CURL_CHUNK_BGN_FUNC_FAIL: @@ -4154,6 +4103,8 @@ static size_t numof_slashes(const char *str) return num; } +#define FTP_MAX_DIR_DEPTH 1000 + /*********************************************************************** * * ftp_parse_url_path() @@ -4161,10 +4112,9 @@ static size_t numof_slashes(const char *str) * Parse the URL path into separate path components. * */ -static -CURLcode ftp_parse_url_path(struct Curl_easy *data, - struct ftp_conn *ftpc, - struct FTP *ftp) +static CURLcode ftp_parse_url_path(struct Curl_easy *data, + struct ftp_conn *ftpc, + struct FTP *ftp) { const char *slashPos = NULL; const char *fileName = NULL; @@ -4186,78 +4136,78 @@ CURLcode ftp_parse_url_path(struct Curl_easy *data, rawPath = ftpc->rawpath; switch(data->set.ftp_filemethod) { - case FTPFILE_NOCWD: /* fastest, but less standard-compliant */ + case FTPFILE_NOCWD: /* fastest, but less standard-compliant */ - if((pathLen > 0) && (rawPath[pathLen - 1] != '/')) - fileName = rawPath; /* this is a full file path */ - /* - else: ftpc->file is not used anywhere other than for operations on - a file. In other words, never for directory operations. - So we can safely leave filename as NULL here and use it as a - argument in dir/file decisions. - */ - break; + if((pathLen > 0) && (rawPath[pathLen - 1] != '/')) + fileName = rawPath; /* this is a full file path */ + /* + else: ftpc->file is not used anywhere other than for operations on + a file. In other words, never for directory operations. + So we can safely leave filename as NULL here and use it as a + argument in dir/file decisions. + */ + break; - case FTPFILE_SINGLECWD: - slashPos = strrchr(rawPath, '/'); - if(slashPos) { - /* get path before last slash, except for / */ - size_t dirlen = slashPos - rawPath; - if(dirlen == 0) - dirlen = 1; - - ftpc->dirs = calloc(1, sizeof(ftpc->dirs[0])); - if(!ftpc->dirs) - return CURLE_OUT_OF_MEMORY; - - ftpc->dirs[0].start = 0; - ftpc->dirs[0].len = (int)dirlen; - ftpc->dirdepth = 1; /* we consider it to be a single dir */ - fileName = slashPos + 1; /* rest is filename */ - } - else - fileName = rawPath; /* filename only (or empty) */ - break; + case FTPFILE_SINGLECWD: + slashPos = strrchr(rawPath, '/'); + if(slashPos) { + /* get path before last slash, except for / */ + size_t dirlen = slashPos - rawPath; + if(dirlen == 0) + dirlen = 1; - default: /* allow pretty much anything */ - case FTPFILE_MULTICWD: { - /* current position: begin of next path component */ - const char *curPos = rawPath; - - /* number of entries to allocate for the 'dirs' array */ - size_t dirAlloc = numof_slashes(rawPath); - - if(dirAlloc >= 1000) - /* suspiciously deep dir hierarchy */ - return CURLE_URL_MALFORMAT; - - if(dirAlloc) { - ftpc->dirs = calloc(dirAlloc, sizeof(ftpc->dirs[0])); - if(!ftpc->dirs) - return CURLE_OUT_OF_MEMORY; - - /* parse the URL path into separate path components */ - while(dirAlloc--) { - const char *spos = strchr(curPos, '/'); - size_t clen = spos - curPos; - - /* path starts with a slash: add that as a directory */ - if(!clen && (ftpc->dirdepth == 0)) - ++clen; - - /* we skip empty path components, like "x//y" since the FTP command - CWD requires a parameter and a non-existent parameter a) does not - work on many servers and b) has no effect on the others. */ - if(clen) { - ftpc->dirs[ftpc->dirdepth].start = (int)(curPos - rawPath); - ftpc->dirs[ftpc->dirdepth].len = (int)clen; - ftpc->dirdepth++; - } - curPos = spos + 1; + ftpc->dirs = curlx_calloc(1, sizeof(ftpc->dirs[0])); + if(!ftpc->dirs) + return CURLE_OUT_OF_MEMORY; + + ftpc->dirs[0].start = 0; + ftpc->dirs[0].len = (int)dirlen; + ftpc->dirdepth = 1; /* we consider it to be a single directory */ + fileName = slashPos + 1; /* rest is filename */ + } + else + fileName = rawPath; /* filename only (or empty) */ + break; + + default: /* allow pretty much anything */ + case FTPFILE_MULTICWD: { + /* current position: begin of next path component */ + const char *curPos = rawPath; + + /* number of entries to allocate for the 'dirs' array */ + size_t dirAlloc = numof_slashes(rawPath); + + if(dirAlloc >= FTP_MAX_DIR_DEPTH) + /* suspiciously deep directory hierarchy */ + return CURLE_URL_MALFORMAT; + + if(dirAlloc) { + ftpc->dirs = curlx_calloc(dirAlloc, sizeof(ftpc->dirs[0])); + if(!ftpc->dirs) + return CURLE_OUT_OF_MEMORY; + + /* parse the URL path into separate path components */ + while(dirAlloc--) { + const char *spos = strchr(curPos, '/'); + size_t clen = spos - curPos; + + /* path starts with a slash: add that as a directory */ + if(!clen && (ftpc->dirdepth == 0)) + ++clen; + + /* we skip empty path components, like "x//y" since the FTP command + CWD requires a parameter and a non-existent parameter a) does not + work on many servers and b) has no effect on the others. */ + if(clen) { + ftpc->dirs[ftpc->dirdepth].start = (int)(curPos - rawPath); + ftpc->dirs[ftpc->dirdepth].len = (int)clen; + ftpc->dirdepth++; } + curPos = spos + 1; } - fileName = curPos; /* the rest is the filename (or empty) */ } + fileName = curPos; /* the rest is the filename (or empty) */ + } break; } /* switch */ @@ -4358,20 +4308,16 @@ static CURLcode ftp_doing(struct Curl_easy *data, * ftp->ctl_valid starts out as FALSE, and gets set to TRUE if we reach the * ftp_done() function without finding any major problem. */ -static -CURLcode ftp_regular_transfer(struct Curl_easy *data, - struct ftp_conn *ftpc, - struct FTP *ftp, - bool *dophase_done) +static CURLcode ftp_regular_transfer(struct Curl_easy *data, + struct ftp_conn *ftpc, + struct FTP *ftp, + bool *dophase_done) { CURLcode result = CURLE_OK; bool connected = FALSE; data->req.size = -1; /* make sure this is unknown at this point */ - Curl_pgrsSetUploadCounter(data, 0); - Curl_pgrsSetDownloadCounter(data, 0); - Curl_pgrsSetUploadSize(data, -1); - Curl_pgrsSetDownloadSize(data, -1); + Curl_pgrsReset(data); ftpc->ctl_valid = TRUE; /* starts good */ @@ -4402,7 +4348,7 @@ static void ftp_easy_dtor(void *key, size_t klen, void *entry) (void)key; (void)klen; Curl_safefree(ftp->pathalloc); - free(ftp); + curlx_free(ftp); } static void ftp_conn_dtor(void *key, size_t klen, void *entry) @@ -4417,7 +4363,7 @@ static void ftp_conn_dtor(void *key, size_t klen, void *entry) Curl_safefree(ftpc->prevpath); Curl_safefree(ftpc->server_os); Curl_pp_disconnect(&ftpc->pp); - free(ftpc); + curlx_free(ftpc); } static void type_url_check(struct Curl_easy *data, struct FTP *ftp) @@ -4456,19 +4402,19 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data, CURLcode result = CURLE_OK; struct ftp_conn *ftpc; - ftp = calloc(1, sizeof(*ftp)); + ftp = curlx_calloc(1, sizeof(*ftp)); if(!ftp || Curl_meta_set(data, CURL_META_FTP_EASY, ftp, ftp_easy_dtor)) return CURLE_OUT_OF_MEMORY; - ftpc = calloc(1, sizeof(*ftpc)); + ftpc = curlx_calloc(1, sizeof(*ftpc)); if(!ftpc || Curl_conn_meta_set(conn, CURL_META_FTP_CONN, ftpc, ftp_conn_dtor)) return CURLE_OUT_OF_MEMORY; /* clone connection related data that is FTP specific */ if(data->set.str[STRING_FTP_ACCOUNT]) { - ftpc->account = strdup(data->set.str[STRING_FTP_ACCOUNT]); + ftpc->account = curlx_strdup(data->set.str[STRING_FTP_ACCOUNT]); if(!ftpc->account) { Curl_conn_meta_remove(conn, CURL_META_FTP_CONN); return CURLE_OUT_OF_MEMORY; @@ -4476,7 +4422,7 @@ static CURLcode ftp_setup_connection(struct Curl_easy *data, } if(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]) { ftpc->alternative_to_user = - strdup(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]); + curlx_strdup(data->set.str[STRING_FTP_ALTERNATIVE_TO_USER]); if(!ftpc->alternative_to_user) { Curl_safefree(ftpc->account); Curl_conn_meta_remove(conn, CURL_META_FTP_CONN); diff --git a/lib/ftp.h b/lib/ftp.h index fdbb4b0539f2..f4ddb1a37cc3 100644 --- a/lib/ftp.h +++ b/lib/ftp.h @@ -61,11 +61,11 @@ enum { FTP_STOR_PREQUOTE, FTP_LIST_PREQUOTE, FTP_POSTQUOTE, - FTP_CWD, /* change dir */ - FTP_MKD, /* if the dir did not exist */ + FTP_CWD, /* change directory */ + FTP_MKD, /* if the directory did not exist */ FTP_MDTM, /* to figure out the datestamp */ FTP_TYPE, /* to set type when doing a head-like request */ - FTP_LIST_TYPE, /* set type when about to do a dir list */ + FTP_LIST_TYPE, /* set type when about to do a directory list */ FTP_RETR_LIST_TYPE, FTP_RETR_TYPE, /* set type when about to RETR a file */ FTP_STOR_TYPE, /* set type when about to STOR a file */ @@ -133,26 +133,22 @@ struct ftp_conn { const char *file; /* url-decoded filename (or path), points into rawpath */ char *rawpath; /* URL decoded, allocated, version of the path */ struct pathcomp *dirs; /* allocated array for path components */ - char *newhost; /* the (allocated) IP addr or hostname to connect the data - connection to */ char *prevpath; /* url-decoded conn->path from the previous transfer */ char transfertype; /* set by ftp_transfertype for use by Curl_client_write()a and others (A/I or zero) */ - curl_off_t retr_size_saved; /* Size of retrieved file saved */ char *server_os; /* The target server operating system. */ curl_off_t known_filesize; /* file size is different from -1, if wildcard LIST parsing was done and wc_statemach set it */ - int dirdepth; /* number of entries used in the 'dirs' array */ - int cwdcount; /* number of CWD commands issued */ int count1; /* general purpose counter for the state machine */ int count2; /* general purpose counter for the state machine */ int count3; /* general purpose counter for the state machine */ - unsigned short newport; /* the port of 'newhost' to connect the data - connection to */ - ftpstate state; /* always use ftp.c:state() to change state! */ - ftpstate state_saved; /* transfer type saved to be reloaded after data - connection is established */ + unsigned short dirdepth; /* number of entries used in the 'dirs' array, + < FTP_MAX_DIR_DEPTH */ + unsigned short cwdcount; /* number of CWD commands issued, + < FTP_MAX_DIR_DEPTH */ + unsigned char state; /* (ftpstate enum) always use ftp.c:state() to change + state! */ 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 ccc; /* ccc level for this connection */ diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c index de573d3c57b5..5836f1cec3b3 100644 --- a/lib/ftplistparser.c +++ b/lib/ftplistparser.c @@ -41,8 +41,6 @@ #ifndef CURL_DISABLE_FTP -#include - #include "urldata.h" #include "fileinfo.h" #include "llist.h" @@ -52,10 +50,6 @@ #include "multiif.h" #include "curlx/strparse.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - typedef enum { PL_UNIX_TOTALSIZE = 0, PL_UNIX_FILETYPE, @@ -185,12 +179,10 @@ static void fileinfo_dtor(void *user, void *element) Curl_fileinfo_cleanup(element); } -CURLcode Curl_wildcard_init(struct WildcardData *wc) +void Curl_wildcard_init(struct WildcardData *wc) { Curl_llist_init(&wc->filelist, fileinfo_dtor); wc->state = CURLWC_INIT; - - return CURLE_OK; } void Curl_wildcard_dtor(struct WildcardData **wcp) @@ -207,37 +199,34 @@ void Curl_wildcard_dtor(struct WildcardData **wcp) DEBUGASSERT(wc->ftpwc == NULL); Curl_llist_destroy(&wc->filelist, NULL); - free(wc->path); + curlx_free(wc->path); wc->path = NULL; - free(wc->pattern); + curlx_free(wc->pattern); wc->pattern = NULL; wc->state = CURLWC_INIT; - free(wc); + curlx_free(wc); *wcp = NULL; } struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void) { - return calloc(1, sizeof(struct ftp_parselist_data)); + return curlx_calloc(1, sizeof(struct ftp_parselist_data)); } - void Curl_ftp_parselist_data_free(struct ftp_parselist_data **parserp) { struct ftp_parselist_data *parser = *parserp; if(parser) Curl_fileinfo_cleanup(parser->file_data); - free(parser); + curlx_free(parser); *parserp = NULL; } - CURLcode Curl_ftp_parselist_geterror(struct ftp_parselist_data *pl_data) { return pl_data->error; } - #define FTP_LP_MALFORMATED_PERM 0x01000000 static unsigned int ftp_pl_get_permission(const char *str) @@ -290,7 +279,7 @@ static unsigned int ftp_pl_get_permission(const char *str) if(str[7] == 'w') permissions |= 1 << 1; else if(str[7] != '-') - permissions |= FTP_LP_MALFORMATED_PERM; + permissions |= FTP_LP_MALFORMATED_PERM; if(str[8] == 'x') permissions |= 1; else if(str[8] == 't') { @@ -436,7 +425,6 @@ static CURLcode parse_unix_totalsize(struct ftp_parselist_data *parser, } else return CURLE_FTP_BAD_FILE_LIST; - } break; } @@ -493,7 +481,7 @@ static CURLcode parse_unix_hlinks(struct ftp_parselist_data *parser, } break; case PL_UNIX_HLINKS_NUMBER: - parser->item_length ++; + parser->item_length++; if(c == ' ') { const char *p = &mem[parser->item_offset]; curl_off_t hlinks; @@ -629,7 +617,7 @@ static CURLcode parse_unix_time(struct ftp_parselist_data *parser, case PL_UNIX_TIME_PREPART1: if(c != ' ') { if(ISALNUM(c) && len) { - parser->item_offset = len -1; + parser->item_offset = len - 1; parser->item_length = 1; parser->state.UNIX.sub.time = PL_UNIX_TIME_PART1; } @@ -674,7 +662,7 @@ static CURLcode parse_unix_time(struct ftp_parselist_data *parser, case PL_UNIX_TIME_PART3: parser->item_length++; if(c == ' ') { - mem[parser->item_offset + parser->item_length -1] = 0; + mem[parser->item_offset + parser->item_length - 1] = 0; parser->offsets.time = parser->item_offset; if(finfo->filetype == CURLFILETYPE_SYMLINK) { parser->state.UNIX.main = PL_UNIX_SYMLINK; @@ -930,7 +918,7 @@ static CURLcode parse_winnt(struct Curl_easy *data, case PL_WINNT_TIME_TIME: if(c == ' ') { parser->offsets.time = parser->item_offset; - mem[parser->item_offset + parser->item_length -1] = 0; + mem[parser->item_offset + parser->item_length - 1] = 0; parser->state.NT.main = PL_WINNT_DIRORSIZE; parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_PRESPACE; parser->item_length = 0; @@ -950,7 +938,7 @@ static CURLcode parse_winnt(struct Curl_easy *data, } break; case PL_WINNT_DIRORSIZE_CONTENT: - parser->item_length ++; + parser->item_length++; if(c == ' ') { mem[parser->item_offset + parser->item_length - 1] = 0; if(strcmp("", mem + parser->item_offset) == 0) { @@ -978,7 +966,7 @@ static CURLcode parse_winnt(struct Curl_easy *data, switch(parser->state.NT.sub.filename) { case PL_WINNT_FILENAME_PRESPACE: if(c != ' ' && len) { - parser->item_offset = len -1; + parser->item_offset = len - 1; parser->item_length = 1; parser->state.NT.sub.filename = PL_WINNT_FILENAME_CONTENT; } @@ -1026,7 +1014,7 @@ static CURLcode parse_winnt(struct Curl_easy *data, size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, void *connptr) { - size_t bufflen = size*nmemb; + size_t bufflen = size * nmemb; struct Curl_easy *data = (struct Curl_easy *)connptr; struct ftp_wc *ftpwc = data->wildcard->ftpwc; struct ftp_parselist_data *parser = ftpwc->parser; diff --git a/lib/ftplistparser.h b/lib/ftplistparser.h index 5ba1f6a97d18..ad8dee74386a 100644 --- a/lib/ftplistparser.h +++ b/lib/ftplistparser.h @@ -65,7 +65,7 @@ struct WildcardData { unsigned char state; /* wildcard_states */ }; -CURLcode Curl_wildcard_init(struct WildcardData *wc); +void Curl_wildcard_init(struct WildcardData *wc); void Curl_wildcard_dtor(struct WildcardData **wcp); struct Curl_easy; diff --git a/lib/functypes.h b/lib/functypes.h index b4dccc0ce487..92f6b45cd200 100644 --- a/lib/functypes.h +++ b/lib/functypes.h @@ -68,7 +68,6 @@ #define SEND_TYPE_RETV int #endif - #ifndef RECV_TYPE_ARG1 #define RECV_TYPE_ARG1 int #endif diff --git a/lib/getenv.c b/lib/getenv.c index 3bfcf707a44b..1955649ace8a 100644 --- a/lib/getenv.c +++ b/lib/getenv.c @@ -24,14 +24,9 @@ #include "curl_setup.h" -#include -#include "curl_memory.h" - -#include "memdebug.h" - -static char *GetEnv(const char *variable) +char *curl_getenv(const char *variable) { -#if defined(CURL_WINDOWS_UWP) || defined(UNDER_CE) || \ +#if defined(CURL_WINDOWS_UWP) || \ defined(__ORBIS__) || defined(__PROSPERO__) /* PlayStation 4 and 5 */ (void)variable; return NULL; @@ -45,9 +40,9 @@ static char *GetEnv(const char *variable) const DWORD max = 32768; /* max env var size from MSCRT source */ for(;;) { - tmp = realloc(buf, rc); + tmp = curlx_realloc(buf, rc); if(!tmp) { - free(buf); + curlx_free(buf); return NULL; } @@ -58,7 +53,7 @@ static char *GetEnv(const char *variable) Since getenv does not make that distinction we ignore it as well. */ rc = GetEnvironmentVariableA(variable, buf, bufsize); if(!rc || rc == bufsize || rc > max) { - free(buf); + curlx_free(buf); return NULL; } @@ -70,11 +65,6 @@ static char *GetEnv(const char *variable) } #else char *env = getenv(variable); - return (env && env[0]) ? strdup(env) : NULL; + return (env && env[0]) ? curlx_strdup(env) : NULL; #endif } - -char *curl_getenv(const char *v) -{ - return GetEnv(v); -} diff --git a/lib/getinfo.c b/lib/getinfo.c index e2a8231d5300..1f429b2227e2 100644 --- a/lib/getinfo.c +++ b/lib/getinfo.c @@ -24,20 +24,14 @@ #include "curl_setup.h" -#include - #include "urldata.h" #include "getinfo.h" #include "cfilters.h" #include "vtls/vtls.h" #include "connect.h" /* Curl_getconnectinfo() */ -#include "progress.h" +#include "bufref.h" #include "curlx/strparse.h" -/* The last #include files should be: */ -#include "curl_memory.h" -#include "memdebug.h" - /* * Initialize statistical and informational data. * @@ -45,7 +39,7 @@ * beginning of a perform session. It must reset the session-info variables, * in particular all variables in struct PureInfo. */ -CURLcode Curl_initinfo(struct Curl_easy *data) +void Curl_initinfo(struct Curl_easy *data) { struct Progress *pro = &data->progress; struct PureInfo *info = &data->info; @@ -74,15 +68,13 @@ CURLcode Curl_initinfo(struct Curl_easy *data) info->httpauthpicked = 0; info->numconnects = 0; - free(info->contenttype); + curlx_free(info->contenttype); info->contenttype = NULL; - free(info->wouldredirect); + curlx_free(info->wouldredirect); info->wouldredirect = NULL; memset(&info->primary, 0, sizeof(info->primary)); - info->primary.remote_port = -1; - info->primary.local_port = -1; info->retry_after = 0; info->conn_scheme = 0; @@ -91,15 +83,16 @@ CURLcode Curl_initinfo(struct Curl_easy *data) #ifdef USE_SSL Curl_ssl_free_certinfo(data); #endif - return CURLE_OK; } static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info, const char **param_charp) { switch(info) { - case CURLINFO_EFFECTIVE_URL: - *param_charp = data->state.url ? data->state.url : ""; + case CURLINFO_EFFECTIVE_URL: { + const char *s = Curl_bufref_ptr(&data->state.url); + *param_charp = s ? s : ""; + } break; case CURLINFO_EFFECTIVE_METHOD: { const char *m = data->set.str[STRING_CUSTOMREQUEST]; @@ -135,12 +128,12 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info, *param_charp = data->info.contenttype; break; case CURLINFO_PRIVATE: - *param_charp = (char *) data->set.private_data; + *param_charp = (char *)data->set.private_data; break; case CURLINFO_FTP_ENTRY_PATH: /* Return the entrypath string from the most recent connection. This pointer was copied from the connectdata structure by FTP. - The actual string may be free()ed by subsequent libcurl calls so + The actual string may be freed by subsequent libcurl calls so it must be copied to a safer area before the next libcurl call. Callers must never free it themselves. */ *param_charp = data->state.most_recent_ftp_entrypath; @@ -152,7 +145,7 @@ static CURLcode getinfo_char(struct Curl_easy *data, CURLINFO info, break; case CURLINFO_REFERER: /* Return the referrer header for this request, or NULL if unset */ - *param_charp = data->state.referer; + *param_charp = Curl_bufref_ptr(&data->state.referer); break; case CURLINFO_PRIMARY_IP: /* Return the ip address of the most recent (primary) connection */ @@ -205,31 +198,31 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info, } lptr; #ifdef DEBUGBUILD - const char *timestr = getenv("CURL_TIME"); - if(timestr) { - curl_off_t val; - curlx_str_number(×tr, &val, TIME_T_MAX); - switch(info) { - case CURLINFO_LOCAL_PORT: + const char *envstr; + + /* use another variable for this to allow different values */ + switch(info) { + case CURLINFO_LOCAL_PORT: + envstr = getenv("CURL_TIME"); + if(envstr) { + curl_off_t val; + curlx_str_number(&envstr, &val, TIME_T_MAX); *param_longp = (long)val; return CURLE_OK; - default: - break; } - } - /* use another variable for this to allow different values */ - timestr = getenv("CURL_DEBUG_SIZE"); - if(timestr) { - curl_off_t val; - curlx_str_number(×tr, &val, LONG_MAX); - switch(info) { - case CURLINFO_HEADER_SIZE: - case CURLINFO_REQUEST_SIZE: + break; + case CURLINFO_HEADER_SIZE: + case CURLINFO_REQUEST_SIZE: + envstr = getenv("CURL_DEBUG_SIZE"); + if(envstr) { + curl_off_t val; + curlx_str_number(&envstr, &val, LONG_MAX); *param_longp = (long)val; return CURLE_OK; - default: - break; } + break; + default: + break; } #endif @@ -305,11 +298,17 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info, break; case CURLINFO_PRIMARY_PORT: /* Return the (remote) port of the most recent (primary) connection */ - *param_longp = data->info.primary.remote_port; + if(CUR_IP_QUAD_HAS_PORTS(&data->info.primary)) + *param_longp = data->info.primary.remote_port; + else + *param_longp = -1; break; case CURLINFO_LOCAL_PORT: /* Return the local port of the most recent (primary) connection */ - *param_longp = data->info.primary.local_port; + if(CUR_IP_QUAD_HAS_PORTS(&data->info.primary)) + *param_longp = data->info.primary.local_port; + else + *param_longp = -1; break; case CURLINFO_PROXY_ERROR: *param_longp = (long)data->info.pxcode; @@ -376,34 +375,35 @@ static CURLcode getinfo_long(struct Curl_easy *data, CURLINFO info, return CURLE_OK; } -#define DOUBLE_SECS(x) (double)(x)/1000000 +#define DOUBLE_SECS(x) (double)(x) / 1000000 static CURLcode getinfo_offt(struct Curl_easy *data, CURLINFO info, curl_off_t *param_offt) { #ifdef DEBUGBUILD - const char *timestr = getenv("CURL_TIME"); - if(timestr) { - curl_off_t val; - curlx_str_number(×tr, &val, CURL_OFF_T_MAX); - - switch(info) { - case CURLINFO_TOTAL_TIME_T: - case CURLINFO_NAMELOOKUP_TIME_T: - case CURLINFO_CONNECT_TIME_T: - case CURLINFO_APPCONNECT_TIME_T: - case CURLINFO_PRETRANSFER_TIME_T: - case CURLINFO_POSTTRANSFER_TIME_T: - case CURLINFO_QUEUE_TIME_T: - case CURLINFO_STARTTRANSFER_TIME_T: - case CURLINFO_REDIRECT_TIME_T: - case CURLINFO_SPEED_DOWNLOAD_T: - case CURLINFO_SPEED_UPLOAD_T: + const char *envstr; + switch(info) { + case CURLINFO_TOTAL_TIME_T: + case CURLINFO_NAMELOOKUP_TIME_T: + case CURLINFO_CONNECT_TIME_T: + case CURLINFO_APPCONNECT_TIME_T: + case CURLINFO_PRETRANSFER_TIME_T: + case CURLINFO_POSTTRANSFER_TIME_T: + case CURLINFO_QUEUE_TIME_T: + case CURLINFO_STARTTRANSFER_TIME_T: + case CURLINFO_REDIRECT_TIME_T: + case CURLINFO_SPEED_DOWNLOAD_T: + case CURLINFO_SPEED_UPLOAD_T: + envstr = getenv("CURL_TIME"); + if(envstr) { + curl_off_t val; + curlx_str_number(&envstr, &val, CURL_OFF_T_MAX); *param_offt = (curl_off_t)val; return CURLE_OK; - default: - break; } + break; + default: + break; } #endif switch(info) { @@ -481,26 +481,28 @@ static CURLcode getinfo_double(struct Curl_easy *data, CURLINFO info, double *param_doublep) { #ifdef DEBUGBUILD - const char *timestr = getenv("CURL_TIME"); - if(timestr) { - curl_off_t val; - curlx_str_number(×tr, &val, CURL_OFF_T_MAX); - - switch(info) { - case CURLINFO_TOTAL_TIME: - case CURLINFO_NAMELOOKUP_TIME: - case CURLINFO_CONNECT_TIME: - case CURLINFO_APPCONNECT_TIME: - case CURLINFO_PRETRANSFER_TIME: - case CURLINFO_STARTTRANSFER_TIME: - case CURLINFO_REDIRECT_TIME: - case CURLINFO_SPEED_DOWNLOAD: - case CURLINFO_SPEED_UPLOAD: + const char *envstr; + + switch(info) { + case CURLINFO_TOTAL_TIME: + case CURLINFO_NAMELOOKUP_TIME: + case CURLINFO_CONNECT_TIME: + case CURLINFO_APPCONNECT_TIME: + case CURLINFO_PRETRANSFER_TIME: + case CURLINFO_STARTTRANSFER_TIME: + case CURLINFO_REDIRECT_TIME: + case CURLINFO_SPEED_DOWNLOAD: + case CURLINFO_SPEED_UPLOAD: + envstr = getenv("CURL_TIME"); + if(envstr) { + curl_off_t val; + curlx_str_number(&envstr, &val, CURL_OFF_T_MAX); *param_doublep = (double)val; return CURLE_OK; - default: - break; } + break; + default: + break; } #endif switch(info) { @@ -575,20 +577,19 @@ static CURLcode getinfo_slist(struct Curl_easy *data, CURLINFO info, *param_slistp = ptr.to_slist; break; case CURLINFO_TLS_SESSION: - case CURLINFO_TLS_SSL_PTR: - { - struct curl_tlssessioninfo **tsip = (struct curl_tlssessioninfo **) - param_slistp; - struct curl_tlssessioninfo *tsi = &data->tsi; - - /* we are exposing a pointer to internal memory with unknown - * lifetime here. */ - *tsip = tsi; - if(!Curl_conn_get_ssl_info(data, data->conn, FIRSTSOCKET, tsi)) { - tsi->backend = Curl_ssl_backend(); - tsi->internals = NULL; - } + case CURLINFO_TLS_SSL_PTR: { + struct curl_tlssessioninfo **tsip = (struct curl_tlssessioninfo **) + param_slistp; + struct curl_tlssessioninfo *tsi = &data->tsi; + + /* we are exposing a pointer to internal memory with unknown + * lifetime here. */ + *tsip = tsi; + if(!Curl_conn_get_ssl_info(data, data->conn, FIRSTSOCKET, tsi)) { + tsi->backend = Curl_ssl_backend(); + tsi->internals = NULL; } + } break; default: return CURLE_UNKNOWN_OPTION; diff --git a/lib/getinfo.h b/lib/getinfo.h index 56bb440b43b2..f5efe4185c50 100644 --- a/lib/getinfo.h +++ b/lib/getinfo.h @@ -24,6 +24,6 @@ * ***************************************************************************/ CURLcode Curl_getinfo(struct Curl_easy *data, CURLINFO info, ...); -CURLcode Curl_initinfo(struct Curl_easy *data); +void Curl_initinfo(struct Curl_easy *data); #endif /* HEADER_CURL_GETINFO_H */ diff --git a/lib/gopher.c b/lib/gopher.c index 6ff47d58c70a..826de91512c1 100644 --- a/lib/gopher.c +++ b/lib/gopher.c @@ -27,23 +27,15 @@ #ifndef CURL_DISABLE_GOPHER #include "urldata.h" -#include #include "transfer.h" #include "sendf.h" +#include "curl_trc.h" #include "cfilters.h" #include "connect.h" -#include "progress.h" #include "gopher.h" #include "select.h" -#include "strdup.h" -#include "vtls/vtls.h" #include "url.h" #include "escape.h" -#include "curlx/warnless.h" - -/* The last 2 #include files should be: */ -#include "curl_memory.h" -#include "memdebug.h" /* * Forward declarations. @@ -140,11 +132,10 @@ static CURLcode gopher_do(struct Curl_easy *data, bool *done) char *gopherpath; char *path = data->state.up.path; char *query = data->state.up.query; - char *sel = NULL; - char *sel_org = NULL; + const char *buf = NULL; + char *buf_alloc = NULL; + size_t nwritten, buf_len; timediff_t timeout_ms; - ssize_t k; - size_t amount, len; int what; *done = TRUE; /* unconditionally */ @@ -155,16 +146,16 @@ static CURLcode gopher_do(struct Curl_easy *data, bool *done) if(query) gopherpath = curl_maprintf("%s?%s", path, query); else - gopherpath = strdup(path); + gopherpath = curlx_strdup(path); if(!gopherpath) return CURLE_OUT_OF_MEMORY; /* Create selector. Degenerate cases: / and /1 => convert to "" */ if(strlen(gopherpath) <= 2) { - sel = (char *)CURL_UNCONST(""); - len = strlen(sel); - free(gopherpath); + buf = ""; + buf_len = 0; + curlx_free(gopherpath); } else { char *newp; @@ -174,36 +165,34 @@ static CURLcode gopher_do(struct Curl_easy *data, bool *done) newp += 2; /* ... and finally unescape */ - result = Curl_urldecode(newp, 0, &sel, &len, REJECT_ZERO); - free(gopherpath); + result = Curl_urldecode(newp, 0, &buf_alloc, &buf_len, REJECT_ZERO); + curlx_free(gopherpath); if(result) return result; - sel_org = sel; + buf = buf_alloc; } - k = curlx_uztosz(len); - - for(;;) { - /* Break out of the loop if the selector is empty because OpenSSL and/or - LibreSSL fail with errno 0 if this is the case. */ - if(strlen(sel) < 1) - break; + for(; buf_len;) { - result = Curl_xfer_send(data, sel, k, FALSE, &amount); + result = Curl_xfer_send(data, buf, buf_len, FALSE, &nwritten); if(!result) { /* Which may not have written it all! */ - result = Curl_client_write(data, CLIENTWRITE_HEADER, sel, amount); + result = Curl_client_write(data, CLIENTWRITE_HEADER, buf, nwritten); if(result) break; - k -= amount; - sel += amount; - if(k < 1) + if(nwritten > buf_len) { + DEBUGASSERT(0); + break; + } + buf_len -= nwritten; + buf += nwritten; + if(!buf_len) break; /* but it did write it all */ } else break; - timeout_ms = Curl_timeleft(data, NULL, FALSE); + timeout_ms = Curl_timeleft_ms(data, FALSE); if(timeout_ms < 0) { result = CURLE_OPERATION_TIMEDOUT; break; @@ -228,10 +217,10 @@ static CURLcode gopher_do(struct Curl_easy *data, bool *done) } } - free(sel_org); + curlx_free(buf_alloc); if(!result) - result = Curl_xfer_send(data, "\r\n", 2, FALSE, &amount); + result = Curl_xfer_send(data, "\r\n", 2, FALSE, &nwritten); if(result) { failf(data, "Failed sending Gopher request"); return result; diff --git a/lib/hash.c b/lib/hash.c index 8312fbf050fd..9ef80dffe990 100644 --- a/lib/hash.c +++ b/lib/hash.c @@ -24,14 +24,7 @@ #include "curl_setup.h" -#include - #include "hash.h" -#include "llist.h" -#include "curl_memory.h" - -/* The last #include file should be: */ -#include "memdebug.h" /* random patterns for API verification */ #ifdef DEBUGBUILD @@ -41,8 +34,7 @@ #if 0 /* useful function for debugging hashes and their contents */ -void Curl_hash_print(struct Curl_hash *h, - void (*func)(void *)) +void Curl_hash_print(struct Curl_hash *h, void (*func)(void *)) { struct Curl_hash_iterator iter; struct Curl_hash_element *he; @@ -84,12 +76,11 @@ void Curl_hash_print(struct Curl_hash *h, * @unittest: 1602 * @unittest: 1603 */ -void -Curl_hash_init(struct Curl_hash *h, - size_t slots, - hash_function hfunc, - comp_function comparator, - Curl_hash_dtor dtor) +void Curl_hash_init(struct Curl_hash *h, + size_t slots, + hash_function hfunc, + comp_function comparator, + Curl_hash_dtor dtor) { DEBUGASSERT(h); DEBUGASSERT(slots); @@ -108,14 +99,15 @@ Curl_hash_init(struct Curl_hash *h, #endif } -static struct Curl_hash_element * -hash_elem_create(const void *key, size_t key_len, const void *p, - Curl_hash_elem_dtor dtor) +static struct Curl_hash_element *hash_elem_create(const void *key, + size_t key_len, + const void *p, + Curl_hash_elem_dtor dtor) { struct Curl_hash_element *he; /* allocate the struct plus memory after it to store the key */ - he = malloc(sizeof(struct Curl_hash_element) + key_len); + he = curlx_malloc(sizeof(struct Curl_hash_element) + key_len); if(he) { he->next = NULL; /* copy the key */ @@ -145,7 +137,7 @@ static void hash_elem_destroy(struct Curl_hash *h, struct Curl_hash_element *he) { hash_elem_clear_ptr(h, he); - free(he); + curlx_free(he); } static void hash_elem_unlink(struct Curl_hash *h, @@ -165,8 +157,8 @@ static void hash_elem_link(struct Curl_hash *h, ++h->size; } -#define CURL_HASH_SLOT(x,y,z) x->table[x->hash_func(y, z, x->slots)] -#define CURL_HASH_SLOT_ADDR(x,y,z) &CURL_HASH_SLOT(x,y,z) +#define CURL_HASH_SLOT(x, y, z) x->table[x->hash_func(y, z, x->slots)] +#define CURL_HASH_SLOT_ADDR(x, y, z) &CURL_HASH_SLOT(x, y, z) void *Curl_hash_add2(struct Curl_hash *h, void *key, size_t key_len, void *p, Curl_hash_elem_dtor dtor) @@ -177,7 +169,7 @@ void *Curl_hash_add2(struct Curl_hash *h, void *key, size_t key_len, void *p, DEBUGASSERT(h->slots); DEBUGASSERT(h->init == HASHINIT); if(!h->table) { - h->table = calloc(h->slots, sizeof(struct Curl_hash_element *)); + h->table = curlx_calloc(h->slots, sizeof(struct Curl_hash_element *)); if(!h->table) return NULL; /* OOM */ } @@ -209,8 +201,7 @@ void *Curl_hash_add2(struct Curl_hash *h, void *key, size_t key_len, void *p, * @unittest: 1602 * @unittest: 1603 */ -void * -Curl_hash_add(struct Curl_hash *h, void *key, size_t key_len, void *p) +void *Curl_hash_add(struct Curl_hash *h, void *key, size_t key_len, void *p) { return Curl_hash_add2(h, key, key_len, p, NULL); } @@ -246,8 +237,7 @@ int Curl_hash_delete(struct Curl_hash *h, void *key, size_t key_len) * * @unittest: 1603 */ -void * -Curl_hash_pick(struct Curl_hash *h, void *key, size_t key_len) +void *Curl_hash_pick(struct Curl_hash *h, void *key, size_t key_len) { DEBUGASSERT(h); DEBUGASSERT(h->init == HASHINIT); @@ -272,8 +262,7 @@ Curl_hash_pick(struct Curl_hash *h, void *key, size_t key_len) * @unittest: 1602 * @unittest: 1603 */ -void -Curl_hash_destroy(struct Curl_hash *h) +void Curl_hash_destroy(struct Curl_hash *h) { DEBUGASSERT(h->init == HASHINIT); if(h->table) { @@ -312,9 +301,8 @@ size_t Curl_hash_count(struct Curl_hash *h) } /* Cleans all entries that pass the comp function criteria. */ -void -Curl_hash_clean_with_criterium(struct Curl_hash *h, void *user, - int (*comp)(void *, void *)) +void Curl_hash_clean_with_criterium(struct Curl_hash *h, void *user, + int (*comp)(void *, void *)) { size_t i; @@ -339,7 +327,7 @@ Curl_hash_clean_with_criterium(struct Curl_hash *h, void *user, size_t Curl_hash_str(void *key, size_t key_length, size_t slots_num) { - const char *key_str = (const char *) key; + const char *key_str = (const char *)key; const char *end = key_str + key_length; size_t h = 5381; diff --git a/lib/hash.h b/lib/hash.h index fcd92db6645d..f669fa580134 100644 --- a/lib/hash.h +++ b/lib/hash.h @@ -26,22 +26,18 @@ #include "curl_setup.h" -#include - -#include "llist.h" - /* Hash function prototype */ -typedef size_t (*hash_function) (void *key, - size_t key_length, - size_t slots_num); +typedef size_t (*hash_function)(void *key, + size_t key_length, + size_t slots_num); /* Comparator function prototype. Compares two keys. */ -typedef size_t (*comp_function) (void *key1, - size_t key1_len, - void *key2, - size_t key2_len); +typedef size_t (*comp_function)(void *key1, + size_t key1_len, + void *key2, + size_t key2_len); typedef void (*Curl_hash_dtor)(void *); @@ -49,10 +45,10 @@ typedef void (*Curl_hash_elem_dtor)(void *key, size_t key_len, void *p); struct Curl_hash_element { struct Curl_hash_element *next; - void *ptr; + void *ptr; Curl_hash_elem_dtor dtor; size_t key_len; - char key[1]; /* allocated memory following the struct */ + char key[1]; /* allocated memory following the struct */ }; struct Curl_hash { @@ -63,7 +59,7 @@ struct Curl_hash { /* Comparator function to compare keys */ comp_function comp_func; /* General element construct, unless element itself carries one */ - Curl_hash_dtor dtor; + Curl_hash_dtor dtor; size_t slots; size_t size; #ifdef DEBUGBUILD @@ -105,7 +101,6 @@ void Curl_hash_start_iterate(struct Curl_hash *hash, struct Curl_hash_element * Curl_hash_next_element(struct Curl_hash_iterator *iter); -void Curl_hash_print(struct Curl_hash *h, - void (*func)(void *)); +void Curl_hash_print(struct Curl_hash *h, void (*func)(void *)); #endif /* HEADER_CURL_HASH_H */ diff --git a/lib/headers.c b/lib/headers.c index 5a5725711317..5ad73dad01b6 100644 --- a/lib/headers.c +++ b/lib/headers.c @@ -25,14 +25,9 @@ #include "curl_setup.h" #include "urldata.h" -#include "strdup.h" #include "sendf.h" +#include "curl_trc.h" #include "headers.h" -#include "curlx/strparse.h" - -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_HEADERS_API) @@ -51,7 +46,7 @@ static void copy_header_external(struct Curl_header_store *hs, h->index = index; /* this will randomly OR a reserved bit for the sole purpose of making it impossible for applications to do == comparisons, as that would otherwise - be very tempting and then lead to the reserved bits not being reserved + be tempting and then lead to the reserved bits not being reserved anymore. */ h->origin = (unsigned int)(hs->type | (1 << 27)); h->anchor = e; @@ -73,7 +68,7 @@ CURLHcode curl_easy_header(CURL *easy, struct Curl_header_store *hs = NULL; struct Curl_header_store *pick = NULL; if(!name || !hout || !data || - (type > (CURLH_HEADER|CURLH_TRAILER|CURLH_CONNECT|CURLH_1XX| + (type > (CURLH_HEADER | CURLH_TRAILER | CURLH_CONNECT | CURLH_1XX | CURLH_PSEUDO)) || !type || (request < -1)) return CURLHE_BAD_ARGUMENT; if(!Curl_llist_count(&data->state.httphdrs)) @@ -219,97 +214,42 @@ static CURLcode namevalue(char *header, size_t hlen, unsigned int type, return CURLE_OK; } -static CURLcode unfold_value(struct Curl_easy *data, const char *value, - size_t vlen) /* length of the incoming header */ -{ - struct Curl_header_store *hs; - struct Curl_header_store *newhs; - size_t olen; /* length of the old value */ - size_t oalloc; /* length of the old name + value + separator */ - size_t offset; - DEBUGASSERT(data->state.prevhead); - hs = data->state.prevhead; - olen = strlen(hs->value); - offset = hs->value - hs->buffer; - oalloc = olen + offset + 1; - - /* skip all trailing space letters */ - while(vlen && ISBLANK(value[vlen - 1])) - vlen--; - - /* save only one leading space */ - while((vlen > 1) && ISBLANK(value[0]) && ISBLANK(value[1])) { - vlen--; - value++; - } - - /* since this header block might move in the realloc below, it needs to - first be unlinked from the list and then re-added again after the - realloc */ - Curl_node_remove(&hs->node); - - /* new size = struct + new value length + old name+value length */ - newhs = Curl_saferealloc(hs, sizeof(*hs) + vlen + oalloc + 1); - if(!newhs) - return CURLE_OUT_OF_MEMORY; - /* ->name and ->value point into ->buffer (to keep the header allocation - in a single memory block), which now potentially have moved. Adjust - them. */ - newhs->name = newhs->buffer; - newhs->value = &newhs->buffer[offset]; - - /* put the data at the end of the previous data, not the newline */ - memcpy(&newhs->value[olen], value, vlen); - newhs->value[olen + vlen] = 0; /* null-terminate at newline */ - - /* insert this node into the list of headers */ - Curl_llist_append(&data->state.httphdrs, newhs, &newhs->node); - data->state.prevhead = newhs; - return CURLE_OK; -} - - /* * Curl_headers_push() gets passed a full HTTP header to store. It gets called - * immediately before the header callback. The header is CRLF terminated. + * immediately before the header callback. The header is CRLF, CR or LF + * terminated. */ CURLcode Curl_headers_push(struct Curl_easy *data, const char *header, + size_t hlen, /* length of header */ unsigned char type) { char *value = NULL; char *name = NULL; - char *end; - size_t hlen; /* length of the incoming header */ struct Curl_header_store *hs; CURLcode result = CURLE_OUT_OF_MEMORY; + const size_t ilen = hlen; if((header[0] == '\r') || (header[0] == '\n')) /* ignore the body separator */ return CURLE_OK; - end = strchr(header, '\r'); - if(!end) { - end = strchr(header, '\n'); - if(!end) - /* neither CR nor LF as terminator is not a valid header */ - return CURLE_WEIRD_SERVER_REPLY; - } - hlen = end - header; - - if((header[0] == ' ') || (header[0] == '\t')) { - if(data->state.prevhead) - /* line folding, append value to the previous header's value */ - return unfold_value(data, header, hlen); - else { - /* cannot unfold without a previous header. Instead of erroring, just - pass the leading blanks. */ - while(hlen && ISBLANK(*header)) { - header++; - hlen--; - } - if(!hlen) - return CURLE_WEIRD_SERVER_REPLY; + /* trim off newline characters */ + if(hlen && (header[hlen - 1] == '\n')) + hlen--; + if(hlen && (header[hlen - 1] == '\r')) + hlen--; + if(hlen == ilen) + /* neither CR nor LF as terminator is not a valid header */ + return CURLE_WEIRD_SERVER_REPLY; + + if(ISBLANK(header[0])) { + /* pass leading blanks */ + while(hlen && ISBLANK(*header)) { + header++; + hlen--; } + if(!hlen) + return CURLE_WEIRD_SERVER_REPLY; } if(Curl_llist_count(&data->state.httphdrs) >= MAX_HTTP_RESP_HEADER_COUNT) { failf(data, "Too many response headers, %d is max", @@ -317,7 +257,7 @@ CURLcode Curl_headers_push(struct Curl_easy *data, const char *header, return CURLE_TOO_LARGE; } - hs = calloc(1, sizeof(*hs) + hlen); + hs = curlx_calloc(1, sizeof(*hs) + hlen); if(!hs) return CURLE_OUT_OF_MEMORY; memcpy(hs->buffer, header, hlen); @@ -336,7 +276,7 @@ CURLcode Curl_headers_push(struct Curl_easy *data, const char *header, } else { failf(data, "Invalid response header"); - free(hs); + curlx_free(hs); } return result; } @@ -364,7 +304,7 @@ static CURLcode hds_cw_collect_write(struct Curl_easy *data, (type & CLIENTWRITE_1XX ? CURLH_1XX : (type & CLIENTWRITE_TRAILER ? CURLH_TRAILER : CURLH_HEADER))); - CURLcode result = Curl_headers_push(data, buf, htype); + CURLcode result = Curl_headers_push(data, buf, blen, htype); CURL_TRC_WRITE(data, "header_collect pushed(type=%x, len=%zu) -> %d", htype, blen, result); if(result) @@ -417,7 +357,7 @@ CURLcode Curl_headers_cleanup(struct Curl_easy *data) for(e = Curl_llist_head(&data->state.httphdrs); e; e = n) { struct Curl_header_store *hs = Curl_node_elem(e); n = Curl_node_next(e); - free(hs); + curlx_free(hs); } headers_reset(data); return CURLE_OK; diff --git a/lib/headers.h b/lib/headers.h index e11fe9804e51..adb03af75b5e 100644 --- a/lib/headers.h +++ b/lib/headers.h @@ -46,7 +46,7 @@ CURLcode Curl_headers_init(struct Curl_easy *data); * Curl_headers_push() gets passed a full header to store. */ CURLcode Curl_headers_push(struct Curl_easy *data, const char *header, - unsigned char type); + size_t hlen, unsigned char type); /* * Curl_headers_cleanup(). Free all stored headers and associated memory. @@ -54,9 +54,9 @@ CURLcode Curl_headers_push(struct Curl_easy *data, const char *header, CURLcode Curl_headers_cleanup(struct Curl_easy *data); #else -#define Curl_headers_init(x) CURLE_OK -#define Curl_headers_push(x,y,z) CURLE_OK -#define Curl_headers_cleanup(x) Curl_nop_stmt +#define Curl_headers_init(x) CURLE_OK +#define Curl_headers_push(x,y,z,a) CURLE_OK +#define Curl_headers_cleanup(x) Curl_nop_stmt #endif #endif /* HEADER_CURL_HEADER_H */ diff --git a/lib/hmac.c b/lib/hmac.c index 5e7dd0df0c2d..f9248b09774e 100644 --- a/lib/hmac.c +++ b/lib/hmac.c @@ -30,14 +30,7 @@ !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) || \ defined(USE_SSL) -#include - #include "curl_hmac.h" -#include "curl_memory.h" -#include "curlx/warnless.h" - -/* The last #include file should be: */ -#include "memdebug.h" /* * Generic HMAC algorithm. @@ -50,10 +43,9 @@ static const unsigned char hmac_ipad = 0x36; static const unsigned char hmac_opad = 0x5C; -struct HMAC_context * -Curl_HMAC_init(const struct HMAC_params *hashparams, - const unsigned char *key, - unsigned int keylen) +struct HMAC_context *Curl_HMAC_init(const struct HMAC_params *hashparams, + const unsigned char *key, + unsigned int keylen) { size_t i; struct HMAC_context *ctxt; @@ -62,21 +54,21 @@ Curl_HMAC_init(const struct HMAC_params *hashparams, /* Create HMAC context. */ i = sizeof(*ctxt) + 2 * hashparams->ctxtsize + hashparams->resultlen; - ctxt = malloc(i); + ctxt = curlx_malloc(i); if(!ctxt) return ctxt; ctxt->hash = hashparams; - ctxt->hashctxt1 = (void *) (ctxt + 1); - ctxt->hashctxt2 = (void *) ((char *) ctxt->hashctxt1 + hashparams->ctxtsize); + ctxt->hashctxt1 = (void *)(ctxt + 1); + ctxt->hashctxt2 = (void *)((char *)ctxt->hashctxt1 + hashparams->ctxtsize); /* If the key is too long, replace it by its hash digest. */ if(keylen > hashparams->maxkeylen) { if(hashparams->hinit(ctxt->hashctxt1)) - return NULL; + goto fail; hashparams->hupdate(ctxt->hashctxt1, key, keylen); - hkey = (unsigned char *) ctxt->hashctxt2 + hashparams->ctxtsize; + hkey = (unsigned char *)ctxt->hashctxt2 + hashparams->ctxtsize; hashparams->hfinal(hkey, ctxt->hashctxt1); key = hkey; keylen = hashparams->resultlen; @@ -85,7 +77,7 @@ Curl_HMAC_init(const struct HMAC_params *hashparams, /* Prime the two hash contexts with the modified key. */ if(hashparams->hinit(ctxt->hashctxt1) || hashparams->hinit(ctxt->hashctxt2)) - return NULL; + goto fail; for(i = 0; i < keylen; i++) { b = (unsigned char)(*key ^ hmac_ipad); @@ -101,6 +93,10 @@ Curl_HMAC_init(const struct HMAC_params *hashparams, /* Done, return pointer to HMAC context. */ return ctxt; + +fail: + curlx_free(ctxt); + return NULL; } int Curl_HMAC_update(struct HMAC_context *ctxt, @@ -112,7 +108,6 @@ int Curl_HMAC_update(struct HMAC_context *ctxt, return 0; } - int Curl_HMAC_final(struct HMAC_context *ctxt, unsigned char *output) { const struct HMAC_params *hashparams = ctxt->hash; @@ -121,12 +116,12 @@ int Curl_HMAC_final(struct HMAC_context *ctxt, unsigned char *output) storage. */ if(!output) - output = (unsigned char *) ctxt->hashctxt2 + ctxt->hash->ctxtsize; + output = (unsigned char *)ctxt->hashctxt2 + ctxt->hash->ctxtsize; hashparams->hfinal(output, ctxt->hashctxt1); hashparams->hupdate(ctxt->hashctxt2, output, hashparams->resultlen); hashparams->hfinal(output, ctxt->hashctxt2); - free(ctxt); + curlx_free(ctxt); return 0; } diff --git a/lib/hostip.c b/lib/hostip.c index 41db274c5d4e..aba12ef791ff 100644 --- a/lib/hostip.c +++ b/lib/hostip.c @@ -42,32 +42,27 @@ #endif #include -#ifndef UNDER_CE #include -#endif #include "urldata.h" -#include "sendf.h" +#include "curl_trc.h" #include "connect.h" #include "hostip.h" #include "hash.h" #include "rand.h" -#include "share.h" +#include "curl_share.h" #include "url.h" #include "curlx/inet_ntop.h" #include "curlx/inet_pton.h" #include "multiif.h" #include "doh.h" -#include "curlx/warnless.h" +#include "progress.h" #include "select.h" #include "strcase.h" #include "easy_lock.h" +#include "curlx/strcopy.h" #include "curlx/strparse.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - #if defined(CURLRES_SYNCH) && \ defined(HAVE_ALARM) && \ defined(SIGALRM) && \ @@ -124,7 +119,7 @@ static void dnscache_entry_free(struct Curl_dns_entry *dns); static void show_resolve_info(struct Curl_easy *data, struct Curl_dns_entry *dns); #else -#define show_resolve_info(x,y) Curl_nop_stmt +#define show_resolve_info(x, y) Curl_nop_stmt #endif /* @@ -164,10 +159,9 @@ void Curl_printable_address(const struct Curl_addrinfo *ai, char *buf, * Create a hostcache id string for the provided host + port, to be used by * the DNS caching. Without alloc. Return length of the id string. */ -static size_t -create_dnscache_id(const char *name, - size_t nlen, /* 0 or actual name length */ - int port, char *ptr, size_t buflen) +static size_t create_dnscache_id(const char *name, + size_t nlen, /* 0 or actual name length */ + int port, char *ptr, size_t buflen) { size_t len = nlen ? nlen : strlen(name); DEBUGASSERT(buflen >= MAX_HOSTCACHE_LEN); @@ -191,16 +185,14 @@ struct dnscache_prune_data { * Returning non-zero means remove the entry, return 0 to keep it in the * cache. */ -static int -dnscache_entry_is_stale(void *datap, void *hc) +static int dnscache_entry_is_stale(void *datap, void *hc) { - struct dnscache_prune_data *prune = - (struct dnscache_prune_data *) datap; - struct Curl_dns_entry *dns = (struct Curl_dns_entry *) hc; + struct dnscache_prune_data *prune = (struct dnscache_prune_data *)datap; + struct Curl_dns_entry *dns = (struct Curl_dns_entry *)hc; if(dns->timestamp.tv_sec || dns->timestamp.tv_usec) { /* get age in milliseconds */ - timediff_t age = curlx_timediff(prune->now, dns->timestamp); + timediff_t age = curlx_ptimediff_ms(&prune->now, &dns->timestamp); if(!dns->addr) age *= 2; /* negative entries age twice as fast */ if(age >= prune->max_age_ms) @@ -215,9 +207,9 @@ dnscache_entry_is_stale(void *datap, void *hc) * Prune the DNS cache. This assumes that a lock has already been taken. * Returns the 'age' of the oldest still kept entry - in milliseconds. */ -static timediff_t -dnscache_prune(struct Curl_hash *hostcache, timediff_t cache_timeout_ms, - struct curltime now) +static timediff_t dnscache_prune(struct Curl_hash *hostcache, + timediff_t cache_timeout_ms, + struct curltime now) { struct dnscache_prune_data user; @@ -226,7 +218,7 @@ dnscache_prune(struct Curl_hash *hostcache, timediff_t cache_timeout_ms, user.oldest_ms = 0; Curl_hash_clean_with_criterium(hostcache, - (void *) &user, + (void *)&user, dnscache_entry_is_stale); return user.oldest_ms; @@ -262,7 +254,6 @@ static void dnscache_unlock(struct Curl_easy *data, void Curl_dnscache_prune(struct Curl_easy *data) { struct Curl_dnscache *dnscache = dnscache_get(data); - struct curltime now; /* the timeout may be set -1 (forever) */ timediff_t timeout_ms = data->set.dns_cache_timeout_ms; @@ -272,11 +263,10 @@ void Curl_dnscache_prune(struct Curl_easy *data) dnscache_lock(data, dnscache); - now = curlx_now(); - do { /* Remove outdated and unused entries from the hostcache */ - timediff_t oldest_ms = dnscache_prune(&dnscache->entries, timeout_ms, now); + timediff_t oldest_ms = + dnscache_prune(&dnscache->entries, timeout_ms, *Curl_pgrs_now(data)); if(Curl_hash_count(&dnscache->entries) > MAX_DNS_CACHE_SIZE) /* prune the ones over half this age */ @@ -342,7 +332,7 @@ static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data, /* See whether the returned entry is stale. Done before we release lock */ struct dnscache_prune_data user; - user.now = curlx_now(); + user.now = *Curl_pgrs_now(data); user.max_age_ms = data->set.dns_cache_timeout_ms; user.oldest_ms = 0; @@ -395,11 +385,10 @@ static struct Curl_dns_entry *fetch_addr(struct Curl_easy *data, * The returned data *MUST* be "released" with Curl_resolv_unlink() after * use, or we will leak memory! */ -struct Curl_dns_entry * -Curl_dnscache_get(struct Curl_easy *data, - const char *hostname, - int port, - int ip_version) +struct Curl_dns_entry *Curl_dnscache_get(struct Curl_easy *data, + const char *hostname, + int port, + int ip_version) { struct Curl_dnscache *dnscache = dnscache_get(data); struct Curl_dns_entry *dns = NULL; @@ -453,7 +442,7 @@ UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data, struct Curl_addrinfo **nodes; infof(data, "Shuffling %i addresses", num_addrs); - nodes = malloc(num_addrs*sizeof(*nodes)); + nodes = curlx_malloc(num_addrs * sizeof(*nodes)); if(nodes) { int i; unsigned int *rnd; @@ -462,10 +451,10 @@ UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data, /* build a plain array of Curl_addrinfo pointers */ nodes[0] = *addr; for(i = 1; i < num_addrs; i++) { - nodes[i] = nodes[i-1]->ai_next; + nodes[i] = nodes[i - 1]->ai_next; } - rnd = malloc(rnd_size); + rnd = curlx_malloc(rnd_size); if(rnd) { /* Fisher-Yates shuffle */ if(Curl_rand(data, (unsigned char *)rnd, rnd_size) == CURLE_OK) { @@ -478,17 +467,17 @@ UNITTEST CURLcode Curl_shuffle_addr(struct Curl_easy *data, /* relink list in the new order */ for(i = 1; i < num_addrs; i++) { - nodes[i-1]->ai_next = nodes[i]; + nodes[i - 1]->ai_next = nodes[i]; } - nodes[num_addrs-1]->ai_next = NULL; + nodes[num_addrs - 1]->ai_next = NULL; *addr = nodes[0]; } - free(rnd); + curlx_free(rnd); } else result = CURLE_OUT_OF_MEMORY; - free(nodes); + curlx_free(nodes); } else result = CURLE_OUT_OF_MEMORY; @@ -511,10 +500,8 @@ Curl_dnscache_mk_entry(struct Curl_easy *data, /* shuffle addresses if requested */ if(data->set.dns_shuffle_addresses) { CURLcode result = Curl_shuffle_addr(data, &addr); - if(result) { - Curl_freeaddrinfo(addr); + if(result) return NULL; - } } #else (void)data; @@ -523,11 +510,9 @@ Curl_dnscache_mk_entry(struct Curl_easy *data, hostlen = strlen(hostname); /* Create a new cache entry */ - dns = calloc(1, sizeof(struct Curl_dns_entry) + hostlen); - if(!dns) { - Curl_freeaddrinfo(addr); + dns = curlx_calloc(1, sizeof(struct Curl_dns_entry) + hostlen); + if(!dns) return NULL; - } dns->refcount = 1; /* the cache has the first reference */ dns->addr = addr; /* this is the address(es) */ @@ -536,7 +521,7 @@ Curl_dnscache_mk_entry(struct Curl_easy *data, dns->timestamp.tv_usec = 0; /* an entry that never goes stale */ } else { - dns->timestamp = curlx_now(); + dns->timestamp = *Curl_pgrs_now(data); } dns->hostport = port; if(hostlen) @@ -571,6 +556,7 @@ dnscache_add_addr(struct Curl_easy *data, dns2 = Curl_hash_add(&dnscache->entries, entry_id, entry_len + 1, (void *)dns); if(!dns2) { + dns->addr = NULL; dnscache_entry_free(dns); return NULL; } @@ -614,7 +600,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(1, sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1); + ca = curlx_calloc(1, sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1); if(!ca) return NULL; @@ -637,11 +623,11 @@ static struct Curl_addrinfo *get_localhost6(int port, const char *name) ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo)); memcpy(ca->ai_addr, &sa6, ss_size); ca->ai_canonname = (char *)ca->ai_addr + ss_size; - strcpy(ca->ai_canonname, name); + curlx_strcopy(ca->ai_canonname, hostlen + 1, name, hostlen); return ca; } #else -#define get_localhost6(x,y) NULL +#define get_localhost6(x, y) NULL #endif /* return a static IPv4 127.0.0.1 for the given name */ @@ -663,7 +649,7 @@ static struct Curl_addrinfo *get_localhost(int port, const char *name) return NULL; memcpy(&sa.sin_addr, &ipv4, sizeof(ipv4)); - ca = calloc(1, sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1); + ca = curlx_calloc(1, sizeof(struct Curl_addrinfo) + ss_size + hostlen + 1); if(!ca) return NULL; ca->ai_flags = 0; @@ -674,7 +660,7 @@ static struct Curl_addrinfo *get_localhost(int port, const char *name) ca->ai_addr = (void *)((char *)ca + sizeof(struct Curl_addrinfo)); memcpy(ca->ai_addr, &sa, ss_size); ca->ai_canonname = (char *)ca->ai_addr + ss_size; - strcpy(ca->ai_canonname, name); + curlx_strcopy(ca->ai_canonname, hostlen + 1, name, hostlen); ca6 = get_localhost6(port, name); if(!ca6) @@ -736,7 +722,6 @@ bool Curl_host_is_ipnum(const char *hostname) return FALSE; } - /* return TRUE if 'part' is a case insensitive tail of 'full' */ static bool tailmatch(const char *full, size_t flen, const char *part, size_t plen) @@ -746,40 +731,6 @@ static bool tailmatch(const char *full, size_t flen, return curl_strnequal(part, &full[flen - plen], plen); } -static struct Curl_addrinfo * -convert_ipaddr_direct(const char *hostname, int port, bool *is_ipaddr) -{ - struct in_addr in; - *is_ipaddr = FALSE; - /* First check if this is an IPv4 address string */ - if(curlx_inet_pton(AF_INET, hostname, &in) > 0) { - /* This is a dotted IP address 123.123.123.123-style */ - *is_ipaddr = TRUE; -#ifdef USE_RESOLVE_ON_IPS - (void)port; - return NULL; -#else - return Curl_ip2addr(AF_INET, &in, hostname, port); -#endif - } -#ifdef USE_IPV6 - else { - struct in6_addr in6; - /* check if this is an IPv6 address string */ - if(curlx_inet_pton(AF_INET6, hostname, &in6) > 0) { - /* This is an IPv6 address literal */ - *is_ipaddr = TRUE; -#ifdef USE_RESOLVE_ON_IPS - return NULL; -#else - return Curl_ip2addr(AF_INET6, &in6, hostname, port); -#endif - } - } -#endif /* USE_IPV6 */ - return NULL; -} - static bool can_resolve_ip_version(struct Curl_easy *data, int ip_version) { #ifdef CURLRES_IPV6 @@ -843,21 +794,26 @@ CURLcode Curl_resolv(struct Curl_easy *data, struct Curl_dnscache *dnscache = dnscache_get(data); struct Curl_dns_entry *dns = NULL; struct Curl_addrinfo *addr = NULL; - int respwait = 0; - bool is_ipaddr; + bool respwait = FALSE; size_t hostname_len; - bool keep_negative = TRUE; /* cache a negative result */ + CURLcode result = CURLE_COULDNT_RESOLVE_HOST; + + *entry = NULL; #ifndef CURL_DISABLE_DOH data->conn->bits.doh = FALSE; /* default is not */ #else (void)allowDOH; #endif - if(!dnscache) + DEBUGASSERT(dnscache); + if(!dnscache) { + result = CURLE_BAD_FUNCTION_ARGUMENT; goto error; + } /* We should intentionally error and not resolve .onion TLDs */ hostname_len = strlen(hostname); + DEBUGASSERT(hostname_len); if(hostname_len >= 7 && (curl_strequal(&hostname[hostname_len - 6], ".onion") || curl_strequal(&hostname[hostname_len - 7], ".onion."))) { @@ -873,6 +829,7 @@ CURLcode Curl_resolv(struct Curl_easy *data, dnscache_unlock(data, dnscache); if(dns) { infof(data, "Hostname %s was found in DNS cache", hostname); + result = CURLE_OK; goto out; } @@ -881,7 +838,8 @@ CURLcode Curl_resolv(struct Curl_easy *data, void *resolver = NULL; int st; #ifdef CURLRES_ASYNCH - if(Curl_async_get_impl(data, &resolver)) + result = Curl_async_get_impl(data, &resolver); + if(result) goto error; #endif Curl_set_in_callback(data, TRUE); @@ -889,56 +847,58 @@ CURLcode Curl_resolv(struct Curl_easy *data, data->set.resolver_start_client); Curl_set_in_callback(data, FALSE); if(st) { - keep_negative = FALSE; + result = CURLE_ABORTED_BY_CALLBACK; goto error; } } - /* shortcut literal IP addresses, if we are not told to resolve them. */ - addr = convert_ipaddr_direct(hostname, port, &is_ipaddr); - if(addr) - goto out; - + if(Curl_is_ipaddr(hostname)) { #ifndef USE_RESOLVE_ON_IPS - /* allowed to convert, hostname is IP address, then NULL means error */ - if(is_ipaddr) - goto error; + /* shortcut literal IP addresses, if we are not told to resolve them. */ + result = Curl_str2addr(hostname, port, &addr); + if(result) + goto error; + goto out; #endif + } - /* Really need a resolver for hostname. */ - if(ip_version == CURL_IPRESOLVE_V6 && !Curl_ipv6works(data)) - goto error; - - if(!is_ipaddr && - (curl_strequal(hostname, "localhost") || - curl_strequal(hostname, "localhost.") || - tailmatch(hostname, hostname_len, STRCONST(".localhost")) || - tailmatch(hostname, hostname_len, STRCONST(".localhost.")))) { + if(curl_strequal(hostname, "localhost") || + curl_strequal(hostname, "localhost.") || + tailmatch(hostname, hostname_len, STRCONST(".localhost")) || + tailmatch(hostname, hostname_len, STRCONST(".localhost."))) { addr = get_localhost(port, hostname); + result = addr ? CURLE_OK : CURLE_OUT_OF_MEMORY; } #ifndef CURL_DISABLE_DOH - else if(!is_ipaddr && allowDOH && data->set.doh) { - addr = Curl_doh(data, hostname, port, ip_version, &respwait); + else if(!Curl_is_ipaddr(hostname) && allowDOH && data->set.doh) { + result = Curl_doh(data, hostname, port, ip_version); + respwait = TRUE; } #endif else { /* Can we provide the requested IP specifics in resolving? */ - if(!can_resolve_ip_version(data, ip_version)) + if(!can_resolve_ip_version(data, ip_version)) { + result = CURLE_COULDNT_RESOLVE_HOST; goto error; + } #ifdef CURLRES_ASYNCH - addr = Curl_async_getaddrinfo(data, hostname, port, ip_version, &respwait); + result = Curl_async_getaddrinfo(data, hostname, port, ip_version); + respwait = TRUE; #else - respwait = 0; /* no async waiting here */ + respwait = FALSE; /* no async waiting here */ addr = Curl_sync_getaddrinfo(data, hostname, port, ip_version); + if(addr) + result = CURLE_OK; #endif } out: - /* We either have found a `dns` or looked up the `addr` - * or `respwait` is set for an async operation. - * Everything else is a failure to resolve. */ - if(dns) { + /* We either have found a `dns` or looked up the `addr` or `respwait` is set + * for an async operation. Everything else is a failure to resolve. */ + if(result) + ; + else if(dns) { if(!dns->addr) { infof(data, "Negative DNS entry"); dns->refcount--; @@ -951,8 +911,12 @@ CURLcode Curl_resolv(struct Curl_easy *data, /* we got a response, create a dns entry, add to cache, return */ dns = Curl_dnscache_mk_entry(data, addr, hostname, 0, port, FALSE); if(!dns || Curl_dnscache_add(data, dns)) { - /* this is OOM or similar, don't store such negative resolves */ - keep_negative = FALSE; + /* this is OOM or similar, do not store such negative resolves */ + Curl_freeaddrinfo(addr); + if(dns) + /* avoid a dangling pointer to addr in the dying dns entry */ + dns->addr = NULL; + result = CURLE_OUT_OF_MEMORY; goto error; } show_resolve_info(data, dns); @@ -964,15 +928,16 @@ CURLcode Curl_resolv(struct Curl_easy *data, *entry = dns; return dns ? CURLE_OK : CURLE_AGAIN; } + result = CURLE_COULDNT_RESOLVE_HOST; } error: if(dns) Curl_resolv_unlink(data, &dns); - *entry = NULL; Curl_async_shutdown(data); - if(keep_negative) + if(result == CURLE_COULDNT_RESOLVE_HOST) store_negative_resolve(data, hostname, port); - return CURLE_COULDNT_RESOLVE_HOST; + DEBUGASSERT(result); + return result; } CURLcode Curl_resolv_blocking(struct Curl_easy *data, @@ -982,7 +947,7 @@ CURLcode Curl_resolv_blocking(struct Curl_easy *data, struct Curl_dns_entry **dnsentry) { CURLcode result; - + DEBUGASSERT(hostname && *hostname); *dnsentry = NULL; result = Curl_resolv(data, hostname, port, ip_version, FALSE, dnsentry); switch(result) { @@ -1009,8 +974,7 @@ CURLcode Curl_resolv_blocking(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. */ -CURL_NORETURN static -void alarmfunc(int sig) +CURL_NORETURN static void alarmfunc(int sig) { (void)sig; siglongjmp(curl_jmpenv, 1); @@ -1047,7 +1011,7 @@ CURLcode Curl_resolv_timeout(struct Curl_easy *data, { #ifdef USE_ALARM_TIMEOUT #ifdef HAVE_SIGACTION - struct sigaction keep_sigact; /* store the old struct here */ + struct sigaction keep_sigact; /* store the old struct here */ volatile bool keep_copysig = FALSE; /* whether old sigact has been saved */ struct sigaction sigact; #else @@ -1060,6 +1024,7 @@ CURLcode Curl_resolv_timeout(struct Curl_easy *data, #endif /* USE_ALARM_TIMEOUT */ CURLcode result; + DEBUGASSERT(hostname && *hostname); *entry = NULL; if(timeoutms < 0) @@ -1086,8 +1051,8 @@ CURLcode Curl_resolv_timeout(struct Curl_easy *data, /* The alarm() function only provides integer second resolution, so if we want to wait less than one second we must bail out already now. */ failf(data, - "remaining timeout of %ld too small to resolve via SIGALRM method", - timeout); + "remaining timeout of %ld too small to resolve via SIGALRM method", + timeout); return CURLE_OPERATION_TIMEDOUT; } /* This allows us to time-out from the name resolver, as the timeout @@ -1129,7 +1094,7 @@ CURLcode Curl_resolv_timeout(struct Curl_easy *data, /* alarm() makes a signal get sent when the timeout fires off, and that will abort system calls */ - prev_alarm = alarm(curlx_sltoui(timeout/1000L)); + prev_alarm = alarm(curlx_sltoui(timeout / 1000L)); } #else /* !USE_ALARM_TIMEOUT */ @@ -1172,14 +1137,14 @@ CURLcode Curl_resolv_timeout(struct Curl_easy *data, the time we spent until now! */ if(prev_alarm) { /* there was an alarm() set before us, now put it back */ - timediff_t elapsed_secs = curlx_timediff(curlx_now(), - data->conn->created) / 1000; + timediff_t elapsed_secs = curlx_ptimediff_ms(Curl_pgrs_now(data), + &data->conn->created) / 1000; /* the alarm period is counted in even number of seconds */ unsigned long alarm_set = (unsigned long)(prev_alarm - elapsed_secs); if(!alarm_set || - ((alarm_set >= 0x80000000) && (prev_alarm < 0x80000000)) ) { + ((alarm_set >= 0x80000000) && (prev_alarm < 0x80000000))) { /* if the alarm time-left reached zero or turned "negative" (counted with unsigned values), we should fire off a SIGALRM here, but we will not, and zero would be to switch it off so we never set it to @@ -1202,10 +1167,10 @@ static void dnscache_entry_free(struct Curl_dns_entry *dns) #ifdef USE_HTTPSRR if(dns->hinfo) { Curl_httpsrr_cleanup(dns->hinfo); - free(dns->hinfo); + curlx_free(dns->hinfo); } #endif - free(dns); + curlx_free(dns); } /* @@ -1231,7 +1196,7 @@ void Curl_resolv_unlink(struct Curl_easy *data, struct Curl_dns_entry **pdns) static void dnscache_entry_dtor(void *entry) { - struct Curl_dns_entry *dns = (struct Curl_dns_entry *) entry; + struct Curl_dns_entry *dns = (struct Curl_dns_entry *)entry; DEBUGASSERT(dns && (dns->refcount > 0)); dns->refcount--; if(dns->refcount == 0) @@ -1335,6 +1300,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) while(*host) { struct Curl_str target; struct Curl_addrinfo *ai; + CURLcode result; if(!curlx_str_single(&host, '[')) { if(curlx_str_until(&host, &target, MAX_IPADR_LEN, ']') || @@ -1350,9 +1316,9 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) } } #ifndef USE_IPV6 - if(memchr(target.str, ':', target.len)) { - infof(data, "Ignoring resolve address '%s', missing IPv6 support.", - address); + if(memchr(curlx_str(&target), ':', curlx_strlen(&target))) { + infof(data, "Ignoring resolve address '%.*s', missing IPv6 support.", + (int)curlx_strlen(&target), curlx_str(&target)); if(curlx_str_single(&host, ',')) goto err; continue; @@ -1365,8 +1331,8 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) memcpy(address, curlx_str(&target), curlx_strlen(&target)); address[curlx_strlen(&target)] = '\0'; - ai = Curl_str2addr(address, (int)port); - if(!ai) { + result = Curl_str2addr(address, (int)port, &ai); + if(result) { infof(data, "Resolve address '%s' found illegal", address); goto err; } @@ -1388,8 +1354,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) error = FALSE; err: if(error) { - failf(data, "Couldn't parse CURLOPT_RESOLVE entry '%s'", - hostp->data); + failf(data, "Could not parse CURLOPT_RESOLVE entry '%s'", hostp->data); Curl_freeaddrinfo(head); return CURLE_SETOPT_OPTION_SYNTAX; } @@ -1425,11 +1390,12 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data) /* put this new host in the cache */ dns = dnscache_add_addr(data, dnscache, head, curlx_str(&source), curlx_strlen(&source), (int)port, permanent); - if(dns) { + if(dns) /* release the returned reference; the cache itself will keep the * entry alive: */ dns->refcount--; - } + else + Curl_freeaddrinfo(head); dnscache_unlock(data, dnscache); diff --git a/lib/hostip.h b/lib/hostip.h index 3eb82cd1498a..8964d29af995 100644 --- a/lib/hostip.h +++ b/lib/hostip.h @@ -25,6 +25,7 @@ ***************************************************************************/ #include "curl_setup.h" + #include "hash.h" #include "curl_addrinfo.h" #include "curlx/timeval.h" /* for timediff_t */ @@ -116,7 +117,6 @@ bool Curl_ipv6works(struct Curl_easy *data); #define Curl_ipv6works(x) FALSE #endif - /* unlink a dns entry, potentially shared with a cache */ void Curl_resolv_unlink(struct Curl_easy *data, struct Curl_dns_entry **pdns); @@ -132,7 +132,7 @@ void Curl_dnscache_prune(struct Curl_easy *data); /* clear the DNS cache */ void Curl_dnscache_clear(struct Curl_easy *data); -/* IPv4 threadsafe resolve function used for synch and asynch builds */ +/* IPv4 thread-safe resolve function used for synch and asynch builds */ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, int port); CURLcode Curl_once_resolved(struct Curl_easy *data, @@ -175,10 +175,9 @@ Curl_dnscache_mk_entry(struct Curl_easy *data, * The returned data *MUST* be "released" with Curl_resolv_unlink() after * use, or we will leak memory! */ -struct Curl_dns_entry * -Curl_dnscache_get(struct Curl_easy *data, - const char *hostname, - int port, int ip_version); +struct Curl_dns_entry *Curl_dnscache_get(struct Curl_easy *data, + const char *hostname, int port, + int ip_version); /* * Curl_dnscache_addr() adds `entry` to the cache, increasing its @@ -196,7 +195,7 @@ CURLcode Curl_loadhostpairs(struct Curl_easy *data); CURLcode Curl_resolv_check(struct Curl_easy *data, struct Curl_dns_entry **dns); #else -#define Curl_resolv_check(x,y) CURLE_NOT_BUILT_IN +#define Curl_resolv_check(x, y) CURLE_NOT_BUILT_IN #endif CURLcode Curl_resolv_pollset(struct Curl_easy *data, struct easy_pollset *ps); diff --git a/lib/hostip4.c b/lib/hostip4.c index e1ed007aafa3..785ca2493316 100644 --- a/lib/hostip4.c +++ b/lib/hostip4.c @@ -44,16 +44,10 @@ #endif #include "urldata.h" -#include "sendf.h" +#include "curl_trc.h" #include "hostip.h" -#include "hash.h" -#include "share.h" #include "url.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - #ifdef CURLRES_SYNCH @@ -97,10 +91,10 @@ struct Curl_addrinfo *Curl_sync_getaddrinfo(struct Curl_easy *data, #if defined(CURLRES_IPV4) && !defined(CURLRES_ARES) && !defined(CURLRES_AMIGA) /* - * Curl_ipv4_resolve_r() - ipv4 threadsafe resolver function. + * Curl_ipv4_resolve_r() - ipv4 thread-safe resolver function. * * This is used for both synchronous and asynchronous resolver builds, - * implying that only threadsafe code and function calls may be used. + * implying that only thread-safe code and function calls may be used. * */ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, @@ -139,7 +133,7 @@ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, */ int h_errnop; - buf = calloc(1, CURL_HOSTENT_SIZE); + buf = curlx_calloc(1, CURL_HOSTENT_SIZE); if(!buf) return NULL; /* major failure */ /* @@ -157,7 +151,7 @@ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, &h_errnop); /* If the buffer is too small, it returns NULL and sets errno to - * ERANGE. The errno is thread safe if this is compiled with + * ERANGE. The errno is thread-safe if this is compiled with * -D_REENTRANT as then the 'errno' variable is a macro defined to get * used properly for threads. */ @@ -170,11 +164,11 @@ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, /* Linux */ (void)gethostbyname_r(hostname, - (struct hostent *)buf, - (char *)buf + sizeof(struct hostent), - CURL_HOSTENT_SIZE - sizeof(struct hostent), - &h, /* DIFFERENCE */ - &h_errnop); + (struct hostent *)buf, + (char *)buf + sizeof(struct hostent), + CURL_HOSTENT_SIZE - sizeof(struct hostent), + &h, /* DIFFERENCE */ + &h_errnop); /* Redhat 8, using glibc 2.2.93 changed the behavior. Now all of a * sudden this function returns EAGAIN if the given buffer size is too * small. Previous versions are known to return ERANGE for the same @@ -253,8 +247,8 @@ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, * Since we do not know how big buffer this particular lookup required, * we cannot realloc down the huge alloc without doing closer analysis of * the returned data. Thus, we always use CURL_HOSTENT_SIZE for every - * name lookup. Fixing this would require an extra malloc() and then - * calling Curl_addrinfo_copy() that subsequent realloc()s down the new + * name lookup. Fixing this would require an extra allocation and then + * calling Curl_addrinfo_copy() that subsequent reallocation down the new * memory area to the actually used amount. */ } @@ -262,12 +256,12 @@ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, #endif /* HAVE_...BYNAME_R_5 || HAVE_...BYNAME_R_6 || HAVE_...BYNAME_R_3 */ { h = NULL; /* set return code to NULL */ - free(buf); + curlx_free(buf); } #else /* (HAVE_GETADDRINFO && HAVE_GETADDRINFO_THREADSAFE) || HAVE_GETHOSTBYNAME_R */ /* - * Here is code for platforms that do not have a thread safe + * Here is code for platforms that do not have a thread-safe * getaddrinfo() nor gethostbyname_r() function or for which * gethostbyname() is the preferred one. */ @@ -280,7 +274,7 @@ struct Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname, ai = Curl_he2ai(h, port); if(buf) /* used a *_r() function */ - free(buf); + curlx_free(buf); } #endif diff --git a/lib/hostip6.c b/lib/hostip6.c index 9419b9e4d5fe..d0d67196c4b3 100644 --- a/lib/hostip6.c +++ b/lib/hostip6.c @@ -45,18 +45,12 @@ #include "urldata.h" #include "cfilters.h" -#include "sendf.h" +#include "curl_trc.h" #include "hostip.h" -#include "hash.h" -#include "share.h" #include "url.h" #include "curlx/inet_pton.h" #include "connect.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - #ifdef CURLRES_SYNCH #ifdef DEBUG_ADDRINFO diff --git a/lib/hsts.c b/lib/hsts.c index 28989764b90f..a4e233e61e9f 100644 --- a/lib/hsts.c +++ b/lib/hsts.c @@ -28,27 +28,21 @@ #include "curl_setup.h" #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_HSTS) -#include #include "urldata.h" #include "llist.h" #include "hsts.h" #include "curl_fopen.h" #include "curl_get_line.h" -#include "sendf.h" #include "parsedate.h" -#include "rename.h" -#include "share.h" -#include "strdup.h" +#include "curl_share.h" #include "curlx/strparse.h" +#include "curlx/timeval.h" +#include "curlx/strcopy.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - -#define MAX_HSTS_LINE 4095 +#define MAX_HSTS_LINE 4095 #define MAX_HSTS_HOSTLEN 2048 #define MAX_HSTS_DATELEN 256 -#define UNLIMITED "unlimited" +#define UNLIMITED "unlimited" #if defined(DEBUGBUILD) || defined(UNITTESTS) /* to play well with debug builds, we can *set* a fixed time this will @@ -72,18 +66,14 @@ static time_t hsts_debugtime(void *unused) struct hsts *Curl_hsts_init(void) { - struct hsts *h = calloc(1, sizeof(struct hsts)); + struct hsts *h = curlx_calloc(1, sizeof(struct hsts)); if(h) { Curl_llist_init(&h->list, NULL); } return h; } -static void hsts_free(struct stsentry *e) -{ - free(CURL_UNCONST(e->host)); - free(e); -} +#define hsts_free(x) curlx_free(x) void Curl_hsts_cleanup(struct hsts **hp) { @@ -96,8 +86,8 @@ void Curl_hsts_cleanup(struct hsts **hp) n = Curl_node_next(e); hsts_free(sts); } - free(h->filename); - free(h); + curlx_free(h->filename); + curlx_free(h); *hp = NULL; } } @@ -115,18 +105,11 @@ static CURLcode hsts_create(struct hsts *h, /* strip off any trailing dot */ --hlen; if(hlen) { - char *duphost; - struct stsentry *sts = calloc(1, sizeof(struct stsentry)); + struct stsentry *sts = curlx_calloc(1, sizeof(struct stsentry) + hlen); if(!sts) return CURLE_OUT_OF_MEMORY; - - duphost = Curl_memdup0(hostname, hlen); - if(!duphost) { - free(sts); - return CURLE_OUT_OF_MEMORY; - } - - sts->host = duphost; + /* the null terminator is already there */ + memcpy(sts->host, hostname, hlen); sts->expires = expires; sts->includeSubDomains = subdomains; Curl_llist_append(&h->list, sts, &sts->node); @@ -252,7 +235,7 @@ struct stsentry *Curl_hsts(struct hsts *h, const char *hostname, if((hlen > MAX_HSTS_HOSTLEN) || !hlen) return NULL; - if(hostname[hlen-1] == '.') + if(hostname[hlen - 1] == '.') /* remove the trailing dot */ --hlen; @@ -269,7 +252,7 @@ struct stsentry *Curl_hsts(struct hsts *h, const char *hostname, ntail = strlen(sts->host); if((subdomain && sts->includeSubDomains) && (ntail < hlen)) { size_t offs = hlen - ntail; - if((hostname[offs-1] == '.') && + if((hostname[offs - 1] == '.') && curl_strnequal(&hostname[offs], sts->host, ntail) && (ntail > blen)) { /* save the tail match with the longest tail */ @@ -277,7 +260,7 @@ struct stsentry *Curl_hsts(struct hsts *h, const char *hostname, blen = ntail; } } - /* avoid curl_strequal because the host name is not null-terminated */ + /* avoid curl_strequal because the hostname is not null-terminated */ if((hlen == ntail) && curl_strnequal(hostname, sts->host, hlen)) return sts; } @@ -298,12 +281,12 @@ static CURLcode hsts_push(struct Curl_easy *data, struct tm stamp; CURLcode result; - e.name = (char *)CURL_UNCONST(sts->host); + e.name = (char *)sts->host; e.namelen = strlen(sts->host); e.includeSubDomains = sts->includeSubDomains; if(sts->expires != TIME_T_MAX) { - result = Curl_gmtime((time_t)sts->expires, &stamp); + result = curlx_gmtime((time_t)sts->expires, &stamp); if(result) return result; @@ -312,10 +295,9 @@ static CURLcode hsts_push(struct Curl_easy *data, stamp.tm_hour, stamp.tm_min, stamp.tm_sec); } else - strcpy(e.expire, UNLIMITED); + curlx_strcopy(e.expire, sizeof(e.expire), UNLIMITED, strlen(UNLIMITED)); - sc = data->set.hsts_write(data, &e, i, - data->set.hsts_write_userp); + sc = data->set.hsts_write(data, &e, i, data->set.hsts_write_userp); *stop = (sc != CURLSTS_OK); return sc == CURLSTS_FAIL ? CURLE_BAD_FUNCTION_ARGUMENT : CURLE_OK; } @@ -327,11 +309,11 @@ static CURLcode hsts_out(struct stsentry *sts, FILE *fp) { struct tm stamp; if(sts->expires != TIME_T_MAX) { - CURLcode result = Curl_gmtime((time_t)sts->expires, &stamp); + CURLcode result = curlx_gmtime((time_t)sts->expires, &stamp); if(result) return result; curl_mfprintf(fp, "%s%s \"%d%02d%02d %02d:%02d:%02d\"\n", - sts->includeSubDomains ? ".": "", sts->host, + sts->includeSubDomains ? "." : "", sts->host, stamp.tm_year + 1900, stamp.tm_mon + 1, stamp.tm_mday, stamp.tm_hour, stamp.tm_min, stamp.tm_sec); } @@ -341,7 +323,6 @@ static CURLcode hsts_out(struct stsentry *sts, FILE *fp) return CURLE_OK; } - /* * Curl_https_save() writes the HSTS cache to file and callback. */ @@ -379,13 +360,13 @@ CURLcode Curl_hsts_save(struct Curl_easy *data, struct hsts *h, break; } curlx_fclose(out); - if(!result && tempstore && Curl_rename(tempstore, file)) + if(!result && tempstore && curlx_rename(tempstore, file)) result = CURLE_WRITE_ERROR; if(result && tempstore) unlink(tempstore); } - free(tempstore); + curlx_free(tempstore); skipsave: if(data->set.hsts_write) { /* if there is a write callback */ @@ -473,7 +454,7 @@ static CURLcode hsts_pull(struct Curl_easy *data, struct hsts *h) char buffer[MAX_HSTS_HOSTLEN + 1]; struct curl_hstsentry e; e.name = buffer; - e.namelen = sizeof(buffer)-1; + e.namelen = sizeof(buffer) - 1; e.includeSubDomains = FALSE; /* default */ e.expire[0] = 0; e.name[0] = 0; /* just to make it clean */ @@ -518,28 +499,32 @@ static CURLcode hsts_load(struct hsts *h, const char *file) /* we need a private copy of the filename so that the hsts cache file name survives an easy handle reset */ - free(h->filename); - h->filename = strdup(file); + curlx_free(h->filename); + h->filename = curlx_strdup(file); if(!h->filename) return CURLE_OUT_OF_MEMORY; fp = curlx_fopen(file, FOPEN_READTEXT); if(fp) { struct dynbuf buf; + bool eof = FALSE; curlx_dyn_init(&buf, MAX_HSTS_LINE); - while(Curl_get_line(&buf, fp)) { - const char *lineptr = curlx_dyn_ptr(&buf); - curlx_str_passblanks(&lineptr); - - /* - * Skip empty or commented lines, since we know the line will have a - * trailing newline from Curl_get_line we can treat length 1 as empty. - */ - if((*lineptr == '#') || strlen(lineptr) <= 1) - continue; - - hsts_add(h, lineptr); - } + do { + result = Curl_get_line(&buf, fp, &eof); + if(!result) { + const char *lineptr = curlx_dyn_ptr(&buf); + curlx_str_passblanks(&lineptr); + + /* + * Skip empty or commented lines, since we know the line will have a + * trailing newline from Curl_get_line we can treat length 1 as empty. + */ + if((*lineptr == '#') || strlen(lineptr) <= 1) + continue; + + hsts_add(h, lineptr); + } + } while(!result && !eof); curlx_dyn_free(&buf); /* free the line buffer */ curlx_fclose(fp); } @@ -567,18 +552,22 @@ CURLcode Curl_hsts_loadcb(struct Curl_easy *data, struct hsts *h) return CURLE_OK; } -void Curl_hsts_loadfiles(struct Curl_easy *data) +CURLcode Curl_hsts_loadfiles(struct Curl_easy *data) { + CURLcode result = CURLE_OK; struct curl_slist *l = data->state.hstslist; if(l) { Curl_share_lock(data, CURL_LOCK_DATA_HSTS, CURL_LOCK_ACCESS_SINGLE); while(l) { - (void)Curl_hsts_loadfile(data, data->hsts, l->data); + result = Curl_hsts_loadfile(data, data->hsts, l->data); + if(result) + break; l = l->next; } Curl_share_unlock(data, CURL_LOCK_DATA_HSTS); } + return result; } #if defined(DEBUGBUILD) || defined(UNITTESTS) diff --git a/lib/hsts.h b/lib/hsts.h index 8ec9637cb0c0..e2c9922f18ef 100644 --- a/lib/hsts.h +++ b/lib/hsts.h @@ -26,7 +26,6 @@ #include "curl_setup.h" #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_HSTS) -#include #include "llist.h" #if defined(DEBUGBUILD) || defined(UNITTESTS) @@ -35,9 +34,9 @@ extern time_t deltatime; struct stsentry { struct Curl_llist_node node; - const char *host; curl_off_t expires; /* the timestamp of this entry's expiry */ BIT(includeSubDomains); + char host[1]; }; /* The HSTS cache. Needs to be able to tailmatch hostnames. */ @@ -59,11 +58,11 @@ CURLcode Curl_hsts_loadfile(struct Curl_easy *data, struct hsts *h, const char *file); CURLcode Curl_hsts_loadcb(struct Curl_easy *data, struct hsts *h); -void Curl_hsts_loadfiles(struct Curl_easy *data); +CURLcode Curl_hsts_loadfiles(struct Curl_easy *data); #else #define Curl_hsts_cleanup(x) -#define Curl_hsts_loadcb(x,y) CURLE_OK -#define Curl_hsts_save(x,y,z) -#define Curl_hsts_loadfiles(x) +#define Curl_hsts_loadcb(x, y) CURLE_OK +#define Curl_hsts_save(x, y, z) +#define Curl_hsts_loadfiles(x) CURLE_OK #endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */ #endif /* HEADER_CURL_HSTS_H */ diff --git a/lib/http.c b/lib/http.c index db37995a12c7..bf38d35dde2b 100644 --- a/lib/http.c +++ b/lib/http.c @@ -48,16 +48,15 @@ #endif #include "urldata.h" -#include #include "transfer.h" #include "sendf.h" +#include "curl_trc.h" #include "formdata.h" #include "mime.h" #include "progress.h" #include "curlx/base64.h" #include "cookie.h" #include "vauth/vauth.h" -#include "vtls/vtls.h" #include "vquic/vquic.h" #include "http_digest.h" #include "http_ntlm.h" @@ -65,7 +64,7 @@ #include "http_aws_sigv4.h" #include "url.h" #include "urlapi-int.h" -#include "share.h" +#include "curl_share.h" #include "hostip.h" #include "dynhds.h" #include "http.h" @@ -76,7 +75,6 @@ #include "strcase.h" #include "content_encoding.h" #include "http_proxy.h" -#include "curlx/warnless.h" #include "http2.h" #include "cfilters.h" #include "connect.h" @@ -84,12 +82,9 @@ #include "altsvc.h" #include "hsts.h" #include "ws.h" -#include "curl_ctype.h" +#include "bufref.h" #include "curlx/strparse.h" - -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" +#include "curlx/timeval.h" /* * Forward declarations. @@ -114,7 +109,8 @@ static CURLcode http_statusline(struct Curl_easy *data, struct connectdata *conn); static CURLcode http_target(struct Curl_easy *data, struct dynbuf *req); static CURLcode http_useragent(struct Curl_easy *data); - +static CURLcode http_write_header(struct Curl_easy *data, + const char *hd, size_t hdlen); /* * HTTP handler interface. @@ -125,13 +121,13 @@ const struct Curl_handler Curl_handler_http = { Curl_http, /* do_it */ Curl_http_done, /* done */ ZERO_NULL, /* do_more */ - Curl_http_connect, /* connect_it */ + ZERO_NULL, /* connect_it */ ZERO_NULL, /* connecting */ ZERO_NULL, /* doing */ ZERO_NULL, /* proto_pollset */ - Curl_http_do_pollset, /* doing_pollset */ + Curl_http_doing_pollset, /* doing_pollset */ ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ + Curl_http_perform_pollset, /* perform_pollset */ ZERO_NULL, /* disconnect */ Curl_http_write_resp, /* write_resp */ Curl_http_write_resp_hd, /* write_resp_hd */ @@ -142,7 +138,8 @@ const struct Curl_handler Curl_handler_http = { CURLPROTO_HTTP, /* protocol */ CURLPROTO_HTTP, /* family */ PROTOPT_CREDSPERREQUEST | /* flags */ - PROTOPT_USERPWDCTRL + PROTOPT_USERPWDCTRL | PROTOPT_CONN_REUSE + }; #ifdef USE_SSL @@ -155,13 +152,13 @@ const struct Curl_handler Curl_handler_https = { Curl_http, /* do_it */ Curl_http_done, /* done */ ZERO_NULL, /* do_more */ - Curl_http_connect, /* connect_it */ + ZERO_NULL, /* connect_it */ NULL, /* connecting */ ZERO_NULL, /* doing */ NULL, /* proto_pollset */ - Curl_http_do_pollset, /* doing_pollset */ + Curl_http_doing_pollset, /* doing_pollset */ ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ + Curl_http_perform_pollset, /* perform_pollset */ ZERO_NULL, /* disconnect */ Curl_http_write_resp, /* write_resp */ Curl_http_write_resp_hd, /* write_resp_hd */ @@ -172,7 +169,7 @@ const struct Curl_handler Curl_handler_https = { CURLPROTO_HTTPS, /* protocol */ CURLPROTO_HTTP, /* family */ PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN | /* flags */ - PROTOPT_USERPWDCTRL + PROTOPT_USERPWDCTRL | PROTOPT_CONN_REUSE }; #endif @@ -220,7 +217,6 @@ CURLcode Curl_http_setup_conn(struct Curl_easy *data, { /* allocate the HTTP-specific struct for the Curl_easy, only to survive during this request */ - connkeep(conn, "HTTP default"); if(data->state.http_neg.wanted == CURL_HTTP_V3x) { /* only HTTP/3, needs to work */ CURLcode result = Curl_conn_may_http3(data, conn, conn->transport_wanted); @@ -259,7 +255,7 @@ char *Curl_checkProxyheaders(struct Curl_easy *data, } #else /* disabled */ -#define Curl_checkProxyheaders(x,y,z,a) NULL +#define Curl_checkProxyheaders(x, y, z, a) NULL #endif static bool http_header_is_empty(const char *header) @@ -277,14 +273,13 @@ static bool http_header_is_empty(const char *header) /* * Strip off leading and trailing whitespace from the value in the given HTTP - * header line and return a strdup()ed copy. Returns NULL in case of - * allocation failure or bad input. Returns an empty string if the header - * value consists entirely of whitespace. + * header line and return a strdup-ed copy in 'valp' - returns an empty + * string if the header value consists entirely of whitespace. * - * If the header is provided as "name;", ending with a semicolon, it must - * return a blank string. + * If the header is provided as "name;", ending with a semicolon, it returns a + * blank string. */ -char *Curl_copy_header_value(const char *header) +static CURLcode copy_custom_value(const char *header, char **valp) { struct Curl_str out; @@ -294,9 +289,37 @@ char *Curl_copy_header_value(const char *header) curlx_str_untilnl(&header, &out, MAX_HTTP_RESP_HEADER_SIZE); curlx_str_trimblanks(&out); - return Curl_memdup0(curlx_str(&out), curlx_strlen(&out)); + *valp = Curl_memdup0(curlx_str(&out), curlx_strlen(&out)); + if(*valp) + return CURLE_OK; + return CURLE_OUT_OF_MEMORY; } /* bad input */ + *valp = NULL; + return CURLE_BAD_FUNCTION_ARGUMENT; +} + +/* + * Strip off leading and trailing whitespace from the value in the given HTTP + * header line and return a strdup-ed copy in 'valp' - returns an empty + * string if the header value consists entirely of whitespace. + * + * This function MUST be used after the header has already been confirmed to + * lead with "word:". + */ +char *Curl_copy_header_value(const char *header) +{ + struct Curl_str out; + + /* find the end of the header name */ + if(!curlx_str_until(&header, &out, MAX_HTTP_RESP_HEADER_SIZE, ':') && + !curlx_str_single(&header, ':')) { + curlx_str_untilnl(&header, &out, MAX_HTTP_RESP_HEADER_SIZE); + curlx_str_trimblanks(&out); + return Curl_memdup0(curlx_str(&out), curlx_strlen(&out)); + } + /* bad input, should never happen */ + DEBUGASSERT(0); return NULL; } @@ -340,7 +363,8 @@ static CURLcode http_output_basic(struct Curl_easy *data, bool proxy) if(!out) return CURLE_OUT_OF_MEMORY; - result = curlx_base64_encode(out, strlen(out), &authorization, &size); + result = curlx_base64_encode((uint8_t *)out, strlen(out), + &authorization, &size); if(result) goto fail; @@ -349,18 +373,18 @@ static CURLcode http_output_basic(struct Curl_easy *data, bool proxy) goto fail; } - free(*userp); + curlx_free(*userp); *userp = curl_maprintf("%sAuthorization: Basic %s\r\n", proxy ? "Proxy-" : "", authorization); - free(authorization); + curlx_free(authorization); if(!*userp) { result = CURLE_OUT_OF_MEMORY; goto fail; } fail: - free(out); + curlx_free(out); return result; } @@ -379,7 +403,7 @@ static CURLcode http_output_bearer(struct Curl_easy *data) CURLcode result = CURLE_OK; userp = &data->state.aptr.userpwd; - free(*userp); + curlx_free(*userp); *userp = curl_maprintf("Authorization: Bearer %s\r\n", data->set.str[STRING_BEARER]); @@ -477,7 +501,7 @@ static CURLcode http_perhapsrewind(struct Curl_easy *data, return CURLE_OK; if(abort_upload) { - /* We'd like to abort the upload - but should we? */ + /* We would like to abort the upload - but should we? */ #ifdef USE_NTLM if((data->state.authproxy.picked == CURLAUTH_NTLM) || (data->state.authhost.picked == CURLAUTH_NTLM)) { @@ -575,7 +599,6 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data) data->state.authproblem = TRUE; else data->info.proxyauthpicked = data->state.authproxy.picked; - } #endif @@ -587,13 +610,14 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data) /* In case this is GSS auth, the newurl field is already allocated so we must make sure to free it before allocating a new one. As figured out in bug #2284386 */ - free(data->req.newurl); - data->req.newurl = strdup(data->state.url); /* clone URL */ + curlx_free(data->req.newurl); + /* clone URL */ + data->req.newurl = Curl_bufref_dup(&data->state.url); if(!data->req.newurl) return CURLE_OUT_OF_MEMORY; } else if((data->req.httpcode < 300) && - (!data->state.authhost.done) && + !data->state.authhost.done && data->req.authneg) { /* no (known) authentication available, authentication is not "done" yet and @@ -601,7 +625,8 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data) we did not try HEAD or GET */ if((data->state.httpreq != HTTPREQ_GET) && (data->state.httpreq != HTTPREQ_HEAD)) { - data->req.newurl = strdup(data->state.url); /* clone URL */ + /* clone URL */ + data->req.newurl = Curl_bufref_dup(&data->state.url); if(!data->req.newurl) return CURLE_OUT_OF_MEMORY; data->state.authhost.done = TRUE; @@ -621,13 +646,12 @@ CURLcode Curl_http_auth_act(struct Curl_easy *data) * Output the correct authentication header depending on the auth type * and whether or not it is to a proxy. */ -static CURLcode -output_auth_headers(struct Curl_easy *data, - struct connectdata *conn, - struct auth *authstatus, - const char *request, - const char *path, - bool proxy) +static CURLcode output_auth_headers(struct Curl_easy *data, + struct connectdata *conn, + struct auth *authstatus, + const char *request, + const char *path, + bool proxy) { const char *auth = NULL; CURLcode result = CURLE_OK; @@ -841,13 +865,12 @@ Curl_http_output_auth(struct Curl_easy *data, #else /* when disabled */ -CURLcode -Curl_http_output_auth(struct Curl_easy *data, - struct connectdata *conn, - const char *request, - Curl_HttpReq httpreq, - const char *path, - bool proxytunnel) +CURLcode Curl_http_output_auth(struct Curl_easy *data, + struct connectdata *conn, + const char *request, + Curl_HttpReq httpreq, + const char *path, + bool proxytunnel) { (void)data; (void)conn; @@ -888,8 +911,8 @@ static CURLcode auth_spnego(struct Curl_easy *data, curlnegotiate *negstate = proxy ? &conn->proxy_negotiate_state : &conn->http_negotiate_state; if(!result) { - free(data->req.newurl); - data->req.newurl = strdup(data->state.url); + curlx_free(data->req.newurl); + data->req.newurl = Curl_bufref_dup(&data->state.url); if(!data->req.newurl) return CURLE_OUT_OF_MEMORY; data->state.authproblem = FALSE; @@ -922,6 +945,8 @@ static CURLcode auth_ntlm(struct Curl_easy *data, if(!result) data->state.authproblem = FALSE; else { + if(result == CURLE_OUT_OF_MEMORY) + return result; infof(data, "NTLM authentication problem, ignoring."); data->state.authproblem = TRUE; } @@ -952,6 +977,8 @@ static CURLcode auth_digest(struct Curl_easy *data, * Digest */ result = Curl_input_digest(data, proxy, auth); if(result) { + if(result == CURLE_OUT_OF_MEMORY) + return result; infof(data, "Digest authentication problem, ignoring."); data->state.authproblem = TRUE; } @@ -1208,18 +1235,15 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl, /* We are asked to automatically set the previous URL as the referer when we get the next URL. We pick the ->url field, which may or may not be 100% correct */ - - if(data->state.referer_alloc) { - Curl_safefree(data->state.referer); - data->state.referer_alloc = FALSE; - } + Curl_bufref_free(&data->state.referer); /* Make a copy of the URL without credentials and fragment */ u = curl_url(); if(!u) return CURLE_OUT_OF_MEMORY; - uc = curl_url_set(u, CURLUPART_URL, data->state.url, 0); + uc = curl_url_set(u, CURLUPART_URL, + Curl_bufref_ptr(&data->state.url), 0); if(!uc) uc = curl_url_set(u, CURLUPART_FRAGMENT, NULL, 0); if(!uc) @@ -1234,8 +1258,7 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl, if(uc || !referer) return CURLE_OUT_OF_MEMORY; - data->state.referer = referer; - data->state.referer_alloc = TRUE; /* yes, free this later */ + Curl_bufref_set(&data->state.referer, referer, 0, curl_free); } } } @@ -1255,7 +1278,7 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl, CURLU_ALLOW_SPACE | (data->set.path_as_is ? CURLU_PATH_AS_IS : 0))); if(uc) { - if(type != FOLLOW_FAKE) { + if((uc == CURLUE_OUT_OF_MEMORY) || (type != FOLLOW_FAKE)) { failf(data, "The redirect target URL could not be parsed: %s", curl_url_strerror(uc)); return Curl_uc_to_curlcode(uc); @@ -1263,7 +1286,7 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl, /* the URL could not be parsed for some reason, but since this is FAKE mode, just duplicate the field as-is */ - follow_url = strdup(newurl); + follow_url = curlx_strdup(newurl); if(!follow_url) return CURLE_OUT_OF_MEMORY; } @@ -1275,7 +1298,6 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl, /* Clear auth if this redirects to a different port number or protocol, unless permitted */ if(!data->set.allow_auth_to_other_hosts && (type != FOLLOW_FAKE)) { - char *portnum; int port; bool clear = FALSE; @@ -1283,14 +1305,19 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl, /* a custom port is used */ port = (int)data->set.use_port; else { + curl_off_t value; + char *portnum; + const char *p; uc = curl_url_get(data->state.uh, CURLUPART_PORT, &portnum, CURLU_DEFAULT_PORT); if(uc) { - free(follow_url); + curlx_free(follow_url); return Curl_uc_to_curlcode(uc); } - port = atoi(portnum); - free(portnum); + p = portnum; + curlx_str_number(&p, &value, 0xffff); + port = (int)value; + curlx_free(portnum); } if(port != data->info.conn_remote_port) { infof(data, "Clear auth, redirects to port from %u to %u", @@ -1302,7 +1329,7 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl, const struct Curl_handler *p; uc = curl_url_get(data->state.uh, CURLUPART_SCHEME, &scheme, 0); if(uc) { - free(follow_url); + curlx_free(follow_url); return Curl_uc_to_curlcode(uc); } @@ -1312,7 +1339,7 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl, data->info.conn_scheme, scheme); clear = TRUE; } - free(scheme); + curlx_free(scheme); } if(clear) { Curl_safefree(data->state.aptr.user); @@ -1337,13 +1364,9 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl, if(disallowport) data->state.allow_port = FALSE; - if(data->state.url_alloc) - Curl_safefree(data->state.url); - - data->state.url = follow_url; - data->state.url_alloc = TRUE; + Curl_bufref_set(&data->state.url, follow_url, 0, curl_free); rewind_result = Curl_req_soft_reset(&data->req, data); - infof(data, "Issue another request to this URL: '%s'", data->state.url); + infof(data, "Issue another request to this URL: '%s'", follow_url); if((data->set.http_follow_mode == CURLFOLLOW_FIRSTONLY) && data->set.str[STRING_CUSTOMREQUEST] && !data->state.http_ignorecustom) { @@ -1366,7 +1389,7 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl, /* 300 - Multiple Choices */ /* 306 - Not used */ /* 307 - Temporary Redirect */ - default: /* for all above (and the unknown ones) */ + default: /* for all above (and the unknown ones) */ /* Some codes are explicitly mentioned since I have checked RFC2616 and * they seem to be OK to POST to. */ @@ -1388,10 +1411,10 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl, * This behavior is forbidden by RFC1945 and the obsolete RFC2616, and * can be overridden with CURLOPT_POSTREDIR. */ - if((data->state.httpreq == HTTPREQ_POST - || data->state.httpreq == HTTPREQ_POST_FORM - || data->state.httpreq == HTTPREQ_POST_MIME) - && !(data->set.keep_post & CURL_REDIR_POST_301)) { + if((data->state.httpreq == HTTPREQ_POST || + data->state.httpreq == HTTPREQ_POST_FORM || + data->state.httpreq == HTTPREQ_POST_MIME) && + !(data->set.keep_post & CURL_REDIR_POST_301)) { http_switch_to_get(data, 301); switch_to_get = TRUE; } @@ -1413,10 +1436,10 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl, * This behavior is forbidden by RFC1945 and the obsolete RFC2616, and * can be overridden with CURLOPT_POSTREDIR. */ - if((data->state.httpreq == HTTPREQ_POST - || data->state.httpreq == HTTPREQ_POST_FORM - || data->state.httpreq == HTTPREQ_POST_MIME) - && !(data->set.keep_post & CURL_REDIR_POST_302)) { + if((data->state.httpreq == HTTPREQ_POST || + data->state.httpreq == HTTPREQ_POST_FORM || + data->state.httpreq == HTTPREQ_POST_MIME) && + !(data->set.keep_post & CURL_REDIR_POST_302)) { http_switch_to_get(data, 302); switch_to_get = TRUE; } @@ -1470,12 +1493,11 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl, * Returns TRUE if 'headerline' contains the 'header' with given 'content'. * Pass headers WITH the colon. */ -bool -Curl_compareheader(const char *headerline, /* line to check */ - const char *header, /* header keyword _with_ colon */ - const size_t hlen, /* len of the keyword in bytes */ - const char *content, /* content string to find */ - const size_t clen) /* len of the content in bytes */ +bool Curl_compareheader(const char *headerline, /* line to check */ + const char *header, /* header keyword _with_ colon */ + const size_t hlen, /* len of the keyword in bytes */ + const char *content, /* content string to find */ + const size_t clen) /* len of the content in bytes */ { /* RFC2616, section 4.2 says: "Each header field consists of a name followed * by a colon (":") and the field value. Field names are case-insensitive. @@ -1511,31 +1533,33 @@ Curl_compareheader(const char *headerline, /* line to check */ return FALSE; /* no match */ } -/* - * Curl_http_connect() performs HTTP stuff to do at connect-time, called from - * the generic Curl_connect(). - */ -CURLcode Curl_http_connect(struct Curl_easy *data, bool *done) -{ - struct connectdata *conn = data->conn; - - /* We default to persistent connections. We set this already in this connect - function to make the reuse checks properly be able to check this bit. */ - connkeep(conn, "HTTP default"); - - return Curl_conn_connect(data, FIRSTSOCKET, FALSE, done); -} - /* this returns the socket to wait for in the DO and DOING state for the multi interface and then we are always _sending_ a request and thus we wait for the single socket to become writable only */ -CURLcode Curl_http_do_pollset(struct Curl_easy *data, - struct easy_pollset *ps) +CURLcode Curl_http_doing_pollset(struct Curl_easy *data, + struct easy_pollset *ps) { /* write mode */ return Curl_pollset_add_out(data, ps, data->conn->sock[FIRSTSOCKET]); } +CURLcode Curl_http_perform_pollset(struct Curl_easy *data, + struct easy_pollset *ps) +{ + struct connectdata *conn = data->conn; + CURLcode result = CURLE_OK; + + if(CURL_WANT_RECV(data)) { + result = Curl_pollset_add_in(data, ps, conn->sock[FIRSTSOCKET]); + } + + /* on a "Expect: 100-continue" timed wait, do not poll for outgoing */ + if(!result && Curl_req_want_send(data) && !http_exp100_is_waiting(data)) { + result = Curl_pollset_add_out(data, ps, conn->sock[FIRSTSOCKET]); + } + return result; +} + /* * Curl_http_done() gets called after a single HTTP request has been * performed. @@ -1551,6 +1575,10 @@ CURLcode Curl_http_done(struct Curl_easy *data, data->state.authhost.multipass = FALSE; data->state.authproxy.multipass = FALSE; + if(curlx_dyn_len(&data->state.headerb)) { + (void)http_write_header(data, curlx_dyn_ptr(&data->state.headerb), + curlx_dyn_len(&data->state.headerb)); + } curlx_dyn_reset(&data->state.headerb); if(status) @@ -1608,14 +1636,14 @@ static unsigned char http_request_version(struct Curl_easy *data) static const char *get_http_string(int httpversion) { switch(httpversion) { - case 30: - return "3"; - case 20: - return "2"; - case 11: - return "1.1"; - default: - return "1.0"; + case 30: + return "3"; + case 20: + return "2"; + case 11: + return "1.1"; + default: + return "1.0"; } } @@ -1685,7 +1713,7 @@ CURLcode Curl_add_custom_headers(struct Curl_easy *data, curlx_str_untilnl(&p, &val, MAX_HTTP_RESP_HEADER_SIZE); curlx_str_trimblanks(&val); if(!curlx_strlen(&val)) - /* no content, don't send this */ + /* no content, do not send this */ continue; } else @@ -1756,7 +1784,7 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data, /* no condition was asked for */ return CURLE_OK; - result = Curl_gmtime(data->set.timevalue, &keeptime); + result = curlx_gmtime(data->set.timevalue, &keeptime); if(result) { failf(data, "Invalid TIMEVALUE"); return result; @@ -1798,7 +1826,7 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data, curl_msnprintf(datestr, sizeof(datestr), "%s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n", condp, - Curl_wkday[tm->tm_wday ? tm->tm_wday-1 : 6], + Curl_wkday[tm->tm_wday ? tm->tm_wday - 1 : 6], tm->tm_mday, Curl_month[tm->tm_mon], tm->tm_year + 1900, @@ -1825,9 +1853,12 @@ void Curl_http_method(struct Curl_easy *data, { Curl_HttpReq httpreq = (Curl_HttpReq)data->state.httpreq; const char *request; - if(data->conn->handler->protocol&(CURLPROTO_WS|CURLPROTO_WSS)) +#ifndef CURL_DISABLE_WEBSOCKETS + if(data->conn->handler->protocol & (CURLPROTO_WS | CURLPROTO_WSS)) httpreq = HTTPREQ_GET; - else if((data->conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_FTP)) && + else +#endif + if((data->conn->handler->protocol & (PROTO_FAMILY_HTTP | CURLPROTO_FTP)) && data->state.upload) httpreq = HTTPREQ_PUT; @@ -1871,13 +1902,12 @@ static CURLcode http_useragent(struct Curl_easy *data) with the user-agent string specified, we erase the previously made string here. */ if(Curl_checkheaders(data, STRCONST("User-Agent"))) { - free(data->state.aptr.uagent); + curlx_free(data->state.aptr.uagent); data->state.aptr.uagent = NULL; } return CURLE_OK; } - static CURLcode http_set_aptr_host(struct Curl_easy *data) { struct connectdata *conn = data->conn; @@ -1886,9 +1916,9 @@ static CURLcode http_set_aptr_host(struct Curl_easy *data) if(!data->state.this_is_a_follow) { /* Free to avoid leaking memory on multiple requests */ - free(data->state.first_host); + curlx_free(data->state.first_host); - data->state.first_host = strdup(conn->host.name); + data->state.first_host = curlx_strdup(conn->host.name); if(!data->state.first_host) return CURLE_OUT_OF_MEMORY; @@ -1906,12 +1936,13 @@ static CURLcode http_set_aptr_host(struct Curl_easy *data) custom Host: header if this is NOT a redirect, as setting Host: in the redirected request is being out on thin ice. Except if the hostname is the same as the first one! */ - char *cookiehost = Curl_copy_header_value(ptr); - if(!cookiehost) - return CURLE_OUT_OF_MEMORY; + char *cookiehost; + CURLcode result = copy_custom_value(ptr, &cookiehost); + if(result) + return result; if(!*cookiehost) /* ignore empty data */ - free(cookiehost); + curlx_free(cookiehost); else { /* If the host begins with '[', we start searching for the port after the bracket has been closed */ @@ -1930,7 +1961,7 @@ static CURLcode http_set_aptr_host(struct Curl_easy *data) if(colon) *colon = 0; /* The host must not include an embedded port number */ } - free(aptr->cookiehost); + curlx_free(aptr->cookiehost); aptr->cookiehost = cookiehost; } #endif @@ -1946,10 +1977,10 @@ static CURLcode http_set_aptr_host(struct Curl_easy *data) [brackets] if the hostname is a plain IPv6-address. RFC2732-style. */ const char *host = conn->host.name; - if(((conn->given->protocol&(CURLPROTO_HTTPS|CURLPROTO_WSS)) && + if(((conn->given->protocol & (CURLPROTO_HTTPS | CURLPROTO_WSS)) && (conn->remote_port == PORT_HTTPS)) || - ((conn->given->protocol&(CURLPROTO_HTTP|CURLPROTO_WS)) && - (conn->remote_port == PORT_HTTP)) ) + ((conn->given->protocol & (CURLPROTO_HTTP | CURLPROTO_WS)) && + (conn->remote_port == PORT_HTTP))) /* if(HTTPS on port 443) OR (HTTP on port 80) then do not include the port number in the host string */ aptr->host = curl_maprintf("Host: %s%s%s\r\n", @@ -2039,7 +2070,7 @@ static CURLcode http_target(struct Curl_easy *data, /* target or URL */ result = curlx_dyn_add(r, data->set.str[STRING_TARGET] ? data->set.str[STRING_TARGET] : url); - free(url); + curlx_free(url); if(result) return result; @@ -2095,7 +2126,7 @@ static CURLcode set_post_reader(struct Curl_easy *data, Curl_HttpReq httpreq) /* Convert the form structure into a mime structure, then keep the conversion */ if(!data->state.formp) { - data->state.formp = calloc(1, sizeof(curl_mimepart)); + data->state.formp = curlx_calloc(1, sizeof(curl_mimepart)); if(!data->state.formp) return CURLE_OUT_OF_MEMORY; Curl_mime_cleanpart(data->state.formp); @@ -2187,9 +2218,11 @@ static CURLcode set_reader(struct Curl_easy *data, Curl_HttpReq httpreq) result = Curl_creader_set_null(data); } else if(data->set.postfields) { - if(postsize > 0) - result = Curl_creader_set_buf(data, data->set.postfields, - (size_t)postsize); + size_t plen = curlx_sotouz_range(postsize, 0, SIZE_MAX); + if(plen == SIZE_MAX) + return CURLE_OUT_OF_MEMORY; + else if(plen) + result = Curl_creader_set_buf(data, data->set.postfields, plen); else result = Curl_creader_set_null(data); } @@ -2367,7 +2400,7 @@ static CURLcode http_add_content_hds(struct Curl_easy *data, (data->req.authneg || !Curl_checkheaders(data, STRCONST("Content-Length")))) { /* we allow replacing this header if not during auth negotiation, - although it is not very wise to actually set your own */ + although it is not wise to actually set your own */ result = curlx_dyn_addf(r, "Content-Length: %" FMT_OFF_T "\r\n", req_clen); } @@ -2428,10 +2461,12 @@ static CURLcode http_cookies(struct Curl_easy *data, int count = 0; if(data->cookies && data->state.cookie_engine) { + bool okay; const char *host = data->state.aptr.cookiehost ? data->state.aptr.cookiehost : data->conn->host.name; Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); - if(!Curl_cookie_getlist(data, data->conn, host, &list)) { + result = Curl_cookie_getlist(data, data->conn, &okay, host, &list); + if(!result && okay) { struct Curl_llist_node *n; size_t clen = 8; /* hold the size of the generated Cookie: header */ @@ -2481,7 +2516,7 @@ static CURLcode http_cookies(struct Curl_easy *data, return result; } #else -#define http_cookies(a,b) CURLE_OK +#define http_cookies(a, b) CURLE_OK #endif static CURLcode http_range(struct Curl_easy *data, @@ -2496,15 +2531,17 @@ static CURLcode http_range(struct Curl_easy *data, if(((httpreq == HTTPREQ_GET) || (httpreq == HTTPREQ_HEAD)) && !Curl_checkheaders(data, STRCONST("Range"))) { /* if a line like this was already allocated, free the previous one */ - free(data->state.aptr.rangeline); + curlx_free(data->state.aptr.rangeline); data->state.aptr.rangeline = curl_maprintf("Range: bytes=%s\r\n", data->state.range); + if(!data->state.aptr.rangeline) + return CURLE_OUT_OF_MEMORY; } else if((httpreq == HTTPREQ_POST || httpreq == HTTPREQ_PUT) && !Curl_checkheaders(data, STRCONST("Content-Range"))) { curl_off_t req_clen = Curl_creader_total_length(data); /* if a line like this was already allocated, free the previous one */ - free(data->state.aptr.rangeline); + curlx_free(data->state.aptr.rangeline); if(data->set.set_resume_from < 0) { /* Upload resume was asked for, but we do not know the size of the @@ -2526,7 +2563,7 @@ static CURLcode http_range(struct Curl_easy *data, data->state.aptr.rangeline = curl_maprintf("Content-Range: bytes %s%" FMT_OFF_T "/" "%" FMT_OFF_T "\r\n", - data->state.range, total_len-1, total_len); + data->state.range, total_len - 1, total_len); } else { /* Range was selected and then we just pass the incoming range and @@ -2657,7 +2694,6 @@ static CURLcode http_add_connection_hd(struct Curl_easy *data, const char *sep = "Connection: "; CURLcode result = CURLE_OK; size_t rlen = curlx_dyn_len(req); - char *value; bool skip; /* Add the 1st custom "Connection: " header, if there is one */ @@ -2665,12 +2701,13 @@ static CURLcode http_add_connection_hd(struct Curl_easy *data, if(curl_strnequal(head->data, "Connection", 10) && Curl_headersep(head->data[10]) && !http_header_is_empty(head->data)) { - value = Curl_copy_header_value(head->data); - if(!value) - return CURLE_OUT_OF_MEMORY; + char *value; + result = copy_custom_value(head->data, &value); + if(result) + return result; result = curlx_dyn_addf(req, "%s%s", sep, value); sep = ", "; - free(value); + curlx_free(value); break; /* leave, having added 1st one */ } } @@ -2749,7 +2786,11 @@ static CURLcode http_add_hd(struct Curl_easy *data, Curl_HttpReq httpreq) { CURLcode result = CURLE_OK; +#if !defined(CURL_DISABLE_ALTSVC) || \ + !defined(CURL_DISABLE_PROXY) || \ + !defined(CURL_DISABLE_WEBSOCKETS) struct connectdata *conn = data->conn; +#endif switch(id) { case H1_HD_REQUEST: /* add the main request stuff */ @@ -2816,8 +2857,10 @@ static CURLcode http_add_hd(struct Curl_easy *data, case H1_HD_REFERER: Curl_safefree(data->state.aptr.ref); - if(data->state.referer && !Curl_checkheaders(data, STRCONST("Referer"))) - result = curlx_dyn_addf(req, "Referer: %s\r\n", data->state.referer); + if(Curl_bufref_ptr(&data->state.referer) && + !Curl_checkheaders(data, STRCONST("Referer"))) + result = curlx_dyn_addf(req, "Referer: %s\r\n", + Curl_bufref_ptr(&data->state.referer)); break; #ifndef CURL_DISABLE_PROXY @@ -2852,7 +2895,7 @@ static CURLcode http_add_hd(struct Curl_easy *data, result = Curl_http2_request_upgrade(req, data); } #ifndef CURL_DISABLE_WEBSOCKETS - if(!result && conn->handler->protocol&(CURLPROTO_WS|CURLPROTO_WSS)) + if(!result && conn->handler->protocol & (CURLPROTO_WS | CURLPROTO_WSS)) result = Curl_ws_request(data, req); #endif break; @@ -2908,6 +2951,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) /* make sure the header buffer is reset - if there are leftovers from a previous transfer */ curlx_dyn_reset(&data->state.headerb); + data->state.maybe_folded = FALSE; if(!data->conn->bits.reuse) { result = http_check_new_conn(data); @@ -2936,12 +2980,14 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) char *pq = NULL; if(data->state.up.query) { pq = curl_maprintf("%s?%s", data->state.up.path, data->state.up.query); - if(!pq) - return CURLE_OUT_OF_MEMORY; + if(!pq) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } } result = Curl_http_output_auth(data, data->conn, method, httpreq, (pq ? pq : data->state.up.path), FALSE); - free(pq); + curlx_free(pq); } if(result) goto out; @@ -2998,7 +3044,6 @@ typedef enum { STATUS_BAD /* not a status line */ } statusline; - /* Check a string for a prefix. Check no more than 'len' bytes */ static bool checkprefixmax(const char *prefix, const char *buffer, size_t len) { @@ -3011,9 +3056,8 @@ static bool checkprefixmax(const char *prefix, const char *buffer, size_t len) * * Returns TRUE if member of the list matches prefix of string */ -static statusline -checkhttpprefix(struct Curl_easy *data, - const char *s, size_t len) +static statusline checkhttpprefix(struct Curl_easy *data, + const char *s, size_t len) { struct curl_slist *head = data->set.http200aliases; statusline rc = STATUS_BAD; @@ -3034,9 +3078,8 @@ checkhttpprefix(struct Curl_easy *data, } #ifndef CURL_DISABLE_RTSP -static statusline -checkrtspprefix(struct Curl_easy *data, - const char *s, size_t len) +static statusline checkrtspprefix(struct Curl_easy *data, + const char *s, size_t len) { statusline result = STATUS_BAD; statusline onmatch = len >= 5 ? STATUS_DONE : STATUS_UNKNOWN; @@ -3048,9 +3091,9 @@ checkrtspprefix(struct Curl_easy *data, } #endif /* CURL_DISABLE_RTSP */ -static statusline -checkprotoprefix(struct Curl_easy *data, struct connectdata *conn, - const char *s, size_t len) +static statusline checkprotoprefix(struct Curl_easy *data, + struct connectdata *conn, + const char *s, size_t len) { #ifndef CURL_DISABLE_RTSP if(conn->handler->protocol & CURLPROTO_RTSP) @@ -3064,17 +3107,17 @@ checkprotoprefix(struct Curl_easy *data, struct connectdata *conn, /* HTTP header has field name `n` (a string constant) */ #define HD_IS(hd, hdlen, n) \ - (((hdlen) >= (sizeof(n)-1)) && curl_strnequal((n), (hd), (sizeof(n)-1))) + (((hdlen) >= (sizeof(n) - 1)) && curl_strnequal((n), (hd), (sizeof(n) - 1))) #define HD_VAL(hd, hdlen, n) \ - ((((hdlen) >= (sizeof(n)-1)) && \ - curl_strnequal((n), (hd), (sizeof(n)-1)))? (hd + (sizeof(n)-1)) : NULL) + ((((hdlen) >= (sizeof(n) - 1)) && \ + curl_strnequal((n), (hd), (sizeof(n) - 1)))? (hd + (sizeof(n) - 1)) : NULL) /* HTTP header has field name `n` (a string constant) and contains `v` * (a string constant) in its value(s) */ #define HD_IS_AND_SAYS(hd, hdlen, n, v) \ (HD_IS(hd, hdlen, n) && \ - ((hdlen) > ((sizeof(n)-1) + (sizeof(v)-1))) && \ + ((hdlen) > ((sizeof(n) - 1) + (sizeof(v) - 1))) && \ Curl_compareheader(hd, STRCONST(n), STRCONST(v))) /* @@ -3186,21 +3229,22 @@ static CURLcode http_header_c(struct Curl_easy *data, return CURLE_OUT_OF_MEMORY; if(!*contenttype) /* ignore empty data */ - free(contenttype); + curlx_free(contenttype); else { - free(data->info.contenttype); + curlx_free(data->info.contenttype); data->info.contenttype = contenttype; } return CURLE_OK; } - if(HD_IS_AND_SAYS(hd, hdlen, "Connection:", "close")) { + if((k->httpversion < 20) && + HD_IS_AND_SAYS(hd, hdlen, "Connection:", "close")) { /* * [RFC 2616, section 8.1.2.1] * "Connection: close" is HTTP/1.1 language and means that * the connection will close when this request has been * served. */ - streamclose(conn, "Connection: close used"); + connclose(conn, "Connection: close used"); return CURLE_OK; } if((k->httpversion == 10) && @@ -3265,23 +3309,31 @@ static CURLcode http_header_l(struct Curl_easy *data, data->info.filetime = k->timeofdoc; return CURLE_OK; } - if((k->httpcode >= 300 && k->httpcode < 400) && - HD_IS(hd, hdlen, "Location:") && - !data->req.location) { + if(HD_IS(hd, hdlen, "Location:")) { /* this is the URL that the server advises us to use instead */ char *location = Curl_copy_header_value(hd); if(!location) return CURLE_OUT_OF_MEMORY; - if(!*location) - /* ignore empty data */ - free(location); + if(!*location || + (data->req.location && !strcmp(data->req.location, location))) { + /* ignore empty header, or exact repeat of a previous one */ + curlx_free(location); + return CURLE_OK; + } else { + /* has value and is not an exact repeat */ + if(data->req.location) { + failf(data, "Multiple Location headers"); + curlx_free(location); + return CURLE_WEIRD_SERVER_REPLY; + } data->req.location = location; - if(data->set.http_follow_mode) { + if((k->httpcode >= 300 && k->httpcode < 400) && + data->set.http_follow_mode) { CURLcode result; DEBUGASSERT(!data->req.newurl); - data->req.newurl = strdup(data->req.location); /* clone */ + data->req.newurl = curlx_strdup(data->req.location); /* clone */ if(!data->req.newurl) return CURLE_OUT_OF_MEMORY; @@ -3336,11 +3388,11 @@ static CURLcode http_header_p(struct Curl_easy *data, #endif if((407 == k->httpcode) && HD_IS(hd, hdlen, "Proxy-authenticate:")) { char *auth = Curl_copy_header_value(hd); - CURLcode result; - if(!auth) - return CURLE_OUT_OF_MEMORY; - result = Curl_http_input_auth(data, TRUE, auth); - free(auth); + CURLcode result = auth ? CURLE_OK : CURLE_OUT_OF_MEMORY; + if(!result) { + result = Curl_http_input_auth(data, TRUE, auth); + curlx_free(auth); + } return result; } #ifdef USE_SPNEGO @@ -3358,7 +3410,7 @@ static CURLcode http_header_p(struct Curl_easy *data, negdata->havenoauthpersist = TRUE; infof(data, "Negotiate: noauthpersist -> %d, header part: %s", negdata->noauthpersist, persistentauth); - free(persistentauth); + curlx_free(persistentauth); } } #endif @@ -3422,11 +3474,12 @@ static CURLcode http_header_s(struct Curl_easy *data, const char *host = data->state.aptr.cookiehost ? data->state.aptr.cookiehost : conn->host.name; const bool secure_context = Curl_secure_context(conn, host); + CURLcode result; Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); - Curl_cookie_add(data, data->cookies, TRUE, FALSE, v, host, - data->state.up.path, secure_context); + result = Curl_cookie_add(data, data->cookies, TRUE, FALSE, v, host, + data->state.up.path, secure_context); Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); - return CURLE_OK; + return result; } #endif #ifndef CURL_DISABLE_HSTS @@ -3444,8 +3497,11 @@ static CURLcode http_header_s(struct Curl_easy *data, if(v) { CURLcode check = Curl_hsts_parse(data->hsts, conn->host.name, v); - if(check) + if(check) { + if(check == CURLE_OUT_OF_MEMORY) + return check; infof(data, "Illegal STS header skipped"); + } #ifdef DEBUGBUILD else infof(data, "Parsed STS header fine (%zu entries)", @@ -3515,9 +3571,11 @@ static CURLcode http_header_w(struct Curl_easy *data, if((401 == k->httpcode) && HD_IS(hd, hdlen, "WWW-Authenticate:")) { char *auth = Curl_copy_header_value(hd); if(!auth) - return CURLE_OUT_OF_MEMORY; - result = Curl_http_input_auth(data, FALSE, auth); - free(auth); + result = CURLE_OUT_OF_MEMORY; + else { + result = Curl_http_input_auth(data, FALSE, auth); + curlx_free(auth); + } } return result; } @@ -3593,15 +3651,15 @@ static CURLcode http_statusline(struct Curl_easy *data, #endif /* no major version switch mid-connection */ if(k->httpversion_sent && - (k->httpversion/10 != k->httpversion_sent/10)) { + (k->httpversion / 10 != k->httpversion_sent / 10)) { failf(data, "Version mismatch (from HTTP/%u to HTTP/%u)", - k->httpversion_sent/10, k->httpversion/10); + k->httpversion_sent / 10, k->httpversion / 10); return CURLE_WEIRD_SERVER_REPLY; } break; default: failf(data, "Unsupported HTTP version (%u.%d) in response", - k->httpversion/10, k->httpversion%10); + k->httpversion / 10, k->httpversion % 10); return CURLE_UNSUPPORTED_PROTOCOL; } @@ -3754,7 +3812,7 @@ static CURLcode http_write_header(struct Curl_easy *data, Curl_debug(data, CURLINFO_HEADER_IN, hd, hdlen); writetype = CLIENTWRITE_HEADER | - ((data->req.httpcode/100 == 1) ? CLIENTWRITE_1XX : 0); + ((data->req.httpcode / 100 == 1) ? CLIENTWRITE_1XX : 0); result = Curl_client_write(data, writetype, hd, hdlen); if(result) @@ -3940,8 +3998,7 @@ static CURLcode http_on_response(struct Curl_easy *data, /* Check if this response means the transfer errored. */ if(http_should_fail(data, data->req.httpcode)) { - failf(data, "The requested URL returned error: %d", - k->httpcode); + failf(data, "The requested URL returned error: %d", k->httpcode); result = CURLE_HTTP_RETURNED_ERROR; goto out; } @@ -3962,7 +4019,7 @@ static CURLcode http_on_response(struct Curl_easy *data, * * The check for close above is done simply because of something * else has already deemed the connection to get closed then - * something else should've considered the big picture and we + * something else should have considered the big picture and we * avoid this check. * */ @@ -3985,16 +4042,19 @@ static CURLcode http_on_response(struct Curl_easy *data, } else { infof(data, "Got HTTP failure 417 while sending data"); - streamclose(conn, - "Stop sending data before everything sent"); + streamclose(conn, "Stop sending data before everything sent"); result = http_perhapsrewind(data, conn); if(result) goto out; } data->state.disableexpect = TRUE; - DEBUGASSERT(!data->req.newurl); - data->req.newurl = strdup(data->state.url); Curl_req_abort_sending(data); + DEBUGASSERT(!data->req.newurl); + data->req.newurl = Curl_bufref_dup(&data->state.url); + if(!data->req.newurl) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } } else if(data->set.http_keep_sending_on_error) { infof(data, "HTTP error before end of send, keep sending"); @@ -4020,7 +4080,6 @@ static CURLcode http_on_response(struct Curl_easy *data, infof(data, "Keep sending data to get tossed away"); k->keepon |= KEEP_SEND; } - } /* If we requested a "no body", this is a good time to get @@ -4030,7 +4089,7 @@ static CURLcode http_on_response(struct Curl_easy *data, 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 would + nothing and can safely return ok now! But for HTTP/2, we would like to call http2_handle_stream_close to properly close a stream. In order to do this, we keep reading until we close the stream. */ @@ -4067,6 +4126,7 @@ static CURLcode http_rw_hd(struct Curl_easy *data, CURLcode result = CURLE_OK; struct SingleRequest *k = &data->req; int writetype; + DEBUGASSERT(!hd[hdlen]); /* null terminated */ *pconsumed = 0; if((0x0a == *hd) || (0x0d == *hd)) { @@ -4127,7 +4187,7 @@ static CURLcode http_rw_hd(struct Curl_easy *data, k->httpcode = (p[0] - '0') * 100 + (p[1] - '0') * 10 + (p[2] - '0'); /* RFC 9112 requires a single space following the status code, - but the browsers don't so let's not insist */ + but the browsers do not so let's not insist */ fine_statusline = TRUE; } } @@ -4215,7 +4275,7 @@ static CURLcode http_rw_hd(struct Curl_easy *data, */ Curl_debug(data, CURLINFO_HEADER_IN, hd, hdlen); - if(k->httpcode/100 == 1) + if(k->httpcode / 100 == 1) writetype |= CLIENTWRITE_1XX; result = Curl_client_write(data, writetype, hd, hdlen); if(result) @@ -4228,6 +4288,21 @@ static CURLcode http_rw_hd(struct Curl_easy *data, return CURLE_OK; } +/* cut off the newline characters */ +static void unfold_header(struct Curl_easy *data) +{ + size_t len = curlx_dyn_len(&data->state.headerb); + char *hd = curlx_dyn_ptr(&data->state.headerb); + if(len && (hd[len - 1] == '\n')) + len--; + if(len && (hd[len - 1] == '\r')) + len--; + while(len && (ISBLANK(hd[len - 1]))) /* strip off trailing whitespace */ + len--; + curlx_dyn_setlen(&data->state.headerb, len); + data->state.leading_unfold = TRUE; +} + /* * Read any HTTP header lines from the server and pass them to the client app. */ @@ -4241,10 +4316,49 @@ static CURLcode http_parse_headers(struct Curl_easy *data, char *end_ptr; bool leftover_body = FALSE; + /* we have bytes for the next header, make sure it is not a folded header + before passing it on */ + if(data->state.maybe_folded && blen) { + if(ISBLANK(buf[0])) { + /* folded, remove the trailing newlines and append the next header */ + unfold_header(data); + } + else { + /* the header data we hold is a complete header, pass it on */ + size_t ignore_this; + result = http_rw_hd(data, curlx_dyn_ptr(&data->state.headerb), + curlx_dyn_len(&data->state.headerb), + NULL, 0, &ignore_this); + curlx_dyn_reset(&data->state.headerb); + if(result) + return result; + } + data->state.maybe_folded = FALSE; + } + /* header line within buffer loop */ *pconsumed = 0; while(blen && k->header) { size_t consumed; + size_t hlen; + char *hd; + size_t unfold_len = 0; + + if(data->state.leading_unfold) { + /* immediately after an unfold, keep only a single whitespace */ + while(blen && ISBLANK(buf[0])) { + buf++; + blen--; + unfold_len++; + } + if(blen) { + /* insert a single space */ + result = curlx_dyn_addn(&data->state.headerb, " ", 1); + if(result) + return result; + data->state.leading_unfold = FALSE; /* done now */ + } + } end_ptr = memchr(buf, '\n', blen); if(!end_ptr) { @@ -4253,7 +4367,7 @@ static CURLcode http_parse_headers(struct Curl_easy *data, result = curlx_dyn_addn(&data->state.headerb, buf, blen); if(result) return result; - *pconsumed += blen; + *pconsumed += blen + unfold_len; if(!k->headerline) { /* check if this looks like a protocol header */ @@ -4282,24 +4396,26 @@ static CURLcode http_parse_headers(struct Curl_easy *data, goto out; /* read more and try again */ } - /* decrease the size of the remaining (supposed) header line */ + /* the size of the remaining header line */ consumed = (end_ptr - buf) + 1; + result = curlx_dyn_addn(&data->state.headerb, buf, consumed); if(result) return result; blen -= consumed; buf += consumed; - *pconsumed += consumed; + *pconsumed += consumed + unfold_len; /**** * We now have a FULL header line in 'headerb'. *****/ + hlen = curlx_dyn_len(&data->state.headerb); + hd = curlx_dyn_ptr(&data->state.headerb); + if(!k->headerline) { - /* the first read header */ - statusline st = checkprotoprefix(data, conn, - curlx_dyn_ptr(&data->state.headerb), - curlx_dyn_len(&data->state.headerb)); + /* the first read "header", the status line */ + statusline st = checkprotoprefix(data, conn, hd, hlen); if(st == STATUS_BAD) { streamclose(conn, "bad HTTP: No end-of-message indicator"); /* this is not the beginning of a protocol first header line. @@ -4317,10 +4433,25 @@ static CURLcode http_parse_headers(struct Curl_easy *data, goto out; } } + else { + if(hlen && !ISNEWLINE(hd[0])) { + /* this is NOT the header separator */ - result = http_rw_hd(data, curlx_dyn_ptr(&data->state.headerb), - curlx_dyn_len(&data->state.headerb), - buf, blen, &consumed); + /* if we have bytes for the next header, check for folding */ + if(blen && ISBLANK(buf[0])) { + /* remove the trailing CRLF and append the next header */ + unfold_header(data); + continue; + } + else if(!blen) { + /* this might be a folded header so deal with it in next invoke */ + data->state.maybe_folded = TRUE; + break; + } + } + } + + result = http_rw_hd(data, hd, hlen, buf, blen, &consumed); /* We are done with this line. We reset because response * processing might switch to HTTP/2 and that might call us * directly again. */ @@ -4351,6 +4482,7 @@ CURLcode Curl_http_write_resp_hd(struct Curl_easy *data, CURLcode result; size_t consumed; char tmp = 0; + DEBUGASSERT(!hd[hdlen]); /* null terminated */ result = http_rw_hd(data, hd, hdlen, &tmp, 0, &consumed); if(!result && is_eos) { @@ -4456,7 +4588,7 @@ CURLcode Curl_http_req_make(struct httpreq **preq, DEBUGASSERT(method && m_len); - req = calloc(1, sizeof(*req) + m_len); + req = curlx_calloc(1, sizeof(*req) + m_len); if(!req) goto out; #if defined(__GNUC__) && __GNUC__ >= 13 @@ -4498,12 +4630,12 @@ CURLcode Curl_http_req_make(struct httpreq **preq, static CURLcode req_assign_url_authority(struct httpreq *req, CURLU *url) { - char *user, *pass, *host, *port; + char *host, *port; struct dynbuf buf; CURLUcode uc; CURLcode result = CURLE_URL_MALFORMAT; - user = pass = host = port = NULL; + host = port = NULL; curlx_dyn_init(&buf, DYN_HTTP_REQUEST); uc = curl_url_get(url, CURLUPART_HOST, &host, 0); @@ -4518,28 +4650,7 @@ static CURLcode req_assign_url_authority(struct httpreq *req, CURLU *url) uc = curl_url_get(url, CURLUPART_PORT, &port, CURLU_NO_DEFAULT_PORT); if(uc && uc != CURLUE_NO_PORT) goto out; - uc = curl_url_get(url, CURLUPART_USER, &user, 0); - if(uc && uc != CURLUE_NO_USER) - goto out; - if(user) { - uc = curl_url_get(url, CURLUPART_PASSWORD, &pass, 0); - if(uc && uc != CURLUE_NO_PASSWORD) - goto out; - } - if(user) { - result = curlx_dyn_add(&buf, user); - if(result) - goto out; - if(pass) { - result = curlx_dyn_addf(&buf, ":%s", pass); - if(result) - goto out; - } - result = curlx_dyn_add(&buf, "@"); - if(result) - goto out; - } result = curlx_dyn_add(&buf, host); if(result) goto out; @@ -4548,17 +4659,12 @@ static CURLcode req_assign_url_authority(struct httpreq *req, CURLU *url) if(result) goto out; } - req->authority = strdup(curlx_dyn_ptr(&buf)); - if(!req->authority) - goto out; - result = CURLE_OK; - + req->authority = curlx_dyn_ptr(&buf); out: - free(user); - free(pass); - free(host); - free(port); - curlx_dyn_free(&buf); + curlx_free(host); + curlx_free(port); + if(result) + curlx_dyn_free(&buf); return result; } @@ -4572,41 +4678,32 @@ static CURLcode req_assign_url_path(struct httpreq *req, CURLU *url) path = query = NULL; curlx_dyn_init(&buf, DYN_HTTP_REQUEST); - uc = curl_url_get(url, CURLUPART_PATH, &path, CURLU_PATH_AS_IS); + uc = curl_url_get(url, CURLUPART_PATH, &path, 0); if(uc) goto out; uc = curl_url_get(url, CURLUPART_QUERY, &query, 0); if(uc && uc != CURLUE_NO_QUERY) goto out; - if(!path && !query) { - req->path = NULL; - } - else if(path && !query) { + if(!query) { req->path = path; path = NULL; } else { - if(path) { - result = curlx_dyn_add(&buf, path); - if(result) - goto out; - } - if(query) { + result = curlx_dyn_add(&buf, path); + if(!result) result = curlx_dyn_addf(&buf, "?%s", query); - if(result) - goto out; - } - req->path = strdup(curlx_dyn_ptr(&buf)); - if(!req->path) + if(result) goto out; + req->path = curlx_dyn_ptr(&buf); } result = CURLE_OK; out: - free(path); - free(query); - curlx_dyn_free(&buf); + curlx_free(path); + curlx_free(query); + if(result) + curlx_dyn_free(&buf); return result; } @@ -4620,7 +4717,7 @@ CURLcode Curl_http_req_make2(struct httpreq **preq, DEBUGASSERT(method && m_len); - req = calloc(1, sizeof(*req) + m_len); + req = curlx_calloc(1, sizeof(*req) + m_len); if(!req) goto out; memcpy(req->method, method, m_len); @@ -4629,7 +4726,7 @@ CURLcode Curl_http_req_make2(struct httpreq **preq, if(uc && uc != CURLUE_NO_SCHEME) goto out; if(!req->scheme && scheme_default) { - req->scheme = strdup(scheme_default); + req->scheme = curlx_strdup(scheme_default); if(!req->scheme) goto out; } @@ -4655,12 +4752,12 @@ CURLcode Curl_http_req_make2(struct httpreq **preq, void Curl_http_req_free(struct httpreq *req) { if(req) { - free(req->scheme); - free(req->authority); - free(req->path); + curlx_free(req->scheme); + curlx_free(req->authority); + curlx_free(req->path); Curl_dynhds_free(&req->headers); Curl_dynhds_free(&req->trailers); - free(req); + curlx_free(req); } } @@ -4743,8 +4840,7 @@ CURLcode Curl_http_req_to_h2(struct dynhds *h2_headers, infof(data, "set pseudo header %s to %s", HTTP_PSEUDO_SCHEME, scheme); } else { - scheme = Curl_conn_is_ssl(data->conn, FIRSTSOCKET) ? - "https" : "http"; + scheme = Curl_conn_is_ssl(data->conn, FIRSTSOCKET) ? "https" : "http"; } } @@ -4798,13 +4894,13 @@ CURLcode Curl_http_resp_make(struct http_resp **presp, struct http_resp *resp; CURLcode result = CURLE_OUT_OF_MEMORY; - resp = calloc(1, sizeof(*resp)); + resp = curlx_calloc(1, sizeof(*resp)); if(!resp) goto out; resp->status = status; if(description) { - resp->description = strdup(description); + resp->description = curlx_strdup(description); if(!resp->description) goto out; } @@ -4822,12 +4918,12 @@ CURLcode Curl_http_resp_make(struct http_resp **presp, void Curl_http_resp_free(struct http_resp *resp) { if(resp) { - free(resp->description); + curlx_free(resp->description); Curl_dynhds_free(&resp->headers); Curl_dynhds_free(&resp->trailers); if(resp->prev) Curl_http_resp_free(resp->prev); - free(resp); + curlx_free(resp); } } @@ -4845,8 +4941,6 @@ static void http_exp100_continue(struct Curl_easy *data, struct cr_exp100_ctx *ctx = reader->ctx; if(ctx->state > EXP100_SEND_DATA) { ctx->state = EXP100_SEND_DATA; - data->req.keepon |= KEEP_SEND; - data->req.keepon &= ~KEEP_SEND_TIMED; Curl_expire_done(data, EXPIRE_100_TIMEOUT); } } @@ -4874,10 +4968,8 @@ static CURLcode cr_exp100_read(struct Curl_easy *data, DEBUGF(infof(data, "cr_exp100_read, start AWAITING_CONTINUE, " "timeout %dms", data->set.expect_100_timeout)); ctx->state = EXP100_AWAITING_CONTINUE; - ctx->start = curlx_now(); + ctx->start = *Curl_pgrs_now(data); Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT); - data->req.keepon &= ~KEEP_SEND; - data->req.keepon |= KEEP_SEND_TIMED; *nread = 0; *eos = FALSE; return CURLE_OK; @@ -4887,11 +4979,9 @@ static CURLcode cr_exp100_read(struct Curl_easy *data, *eos = FALSE; return CURLE_READ_ERROR; case EXP100_AWAITING_CONTINUE: - ms = curlx_timediff(curlx_now(), ctx->start); + ms = curlx_ptimediff_ms(Curl_pgrs_now(data), &ctx->start); if(ms < data->set.expect_100_timeout) { DEBUGF(infof(data, "cr_exp100_read, AWAITING_CONTINUE, not expired")); - data->req.keepon &= ~KEEP_SEND; - data->req.keepon |= KEEP_SEND_TIMED; *nread = 0; *eos = FALSE; return CURLE_OK; @@ -4911,7 +5001,6 @@ static void cr_exp100_done(struct Curl_easy *data, { struct cr_exp100_ctx *ctx = reader->ctx; ctx->state = premature ? EXP100_FAILED : EXP100_SEND_DATA; - data->req.keepon &= ~KEEP_SEND_TIMED; Curl_expire_done(data, EXPIRE_100_TIMEOUT); } @@ -4934,8 +5023,7 @@ static CURLcode http_exp100_add_reader(struct Curl_easy *data) struct Curl_creader *reader = NULL; CURLcode result; - result = Curl_creader_create(&reader, data, &cr_exp100, - CURL_CR_PROTOCOL); + result = Curl_creader_create(&reader, data, &cr_exp100, CURL_CR_PROTOCOL); if(!result) result = Curl_creader_add(data, reader); if(!result) { diff --git a/lib/http.h b/lib/http.h index 67ef17f5b953..7f944ea33b6a 100644 --- a/lib/http.h +++ b/lib/http.h @@ -27,7 +27,6 @@ #include "bufq.h" #include "dynhds.h" -#include "ws.h" typedef enum { HTTPREQ_GET, @@ -38,7 +37,6 @@ typedef enum { HTTPREQ_HEAD } Curl_HttpReq; - /* When redirecting transfers. */ typedef enum { FOLLOW_NONE, /* not used within the function, just a placeholder to @@ -55,7 +53,6 @@ typedef enum { /* bitmask of CURL_HTTP_V* values */ typedef unsigned char http_majors; - #ifndef CURL_DISABLE_HTTP #ifdef USE_HTTP3 @@ -74,6 +71,7 @@ struct http_negotiation { unsigned char rcvd_min; /* minimum version seen in responses, 09, 10, 11 */ http_majors wanted; /* wanted major versions when talking to server */ http_majors allowed; /* allowed major versions when talking to server */ + http_majors preferred; /* preferred major version when talking to server */ BIT(h2_upgrade); /* Do HTTP Upgrade from 1.1 to 2 */ BIT(h2_prior_knowledge); /* Directly do HTTP/2 without ALPN/SSL */ BIT(accept_09); /* Accept an HTTP/0.9 response */ @@ -114,9 +112,10 @@ 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); -CURLcode Curl_http_do_pollset(struct Curl_easy *data, - struct easy_pollset *ps); +CURLcode Curl_http_doing_pollset(struct Curl_easy *data, + struct easy_pollset *ps); +CURLcode Curl_http_perform_pollset(struct Curl_easy *data, + struct easy_pollset *ps); CURLcode Curl_http_write_resp(struct Curl_easy *data, const char *buf, size_t blen, bool is_eos); @@ -138,7 +137,7 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl, selected to use no auth at all. Ie, we actively select no auth, as opposed to not having one selected. The other CURLAUTH_* defines are present in the public curl/curl.h header. */ -#define CURLAUTH_PICKNONE (1<<30) /* do not use auth */ +#define CURLAUTH_PICKNONE (1 << 30) /* do not use auth */ /* MAX_INITIAL_POST_SIZE indicates the number of bytes that will make the POST data get included in the initial data chunk sent to the server. If the @@ -153,7 +152,7 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl, It must not be greater than 64K to work on VMS. */ #ifndef MAX_INITIAL_POST_SIZE -#define MAX_INITIAL_POST_SIZE (64*1024) +#define MAX_INITIAL_POST_SIZE (64 * 1024) #endif /* EXPECT_100_THRESHOLD is the request body size limit for when libcurl will @@ -162,13 +161,13 @@ CURLcode Curl_http_follow(struct Curl_easy *data, const char *newurl, * */ #ifndef EXPECT_100_THRESHOLD -#define EXPECT_100_THRESHOLD (1024*1024) +#define EXPECT_100_THRESHOLD (1024 * 1024) #endif /* MAX_HTTP_RESP_HEADER_SIZE is the maximum size of all response headers combined that libcurl allows for a single HTTP response, any HTTP version. This count includes CONNECT response headers. */ -#define MAX_HTTP_RESP_HEADER_SIZE (300*1024) +#define MAX_HTTP_RESP_HEADER_SIZE (300 * 1024) /* MAX_HTTP_RESP_HEADER_COUNT is the maximum number of response headers that libcurl allows for a single HTTP response, including CONNECT and @@ -213,7 +212,6 @@ Curl_http_output_auth(struct Curl_easy *data, /* Decode HTTP status code string. */ CURLcode Curl_http_decode_status(int *pstatus, const char *s, size_t len); - /** * All about a core HTTP request, excluding body and trailers */ @@ -241,11 +239,11 @@ CURLcode Curl_http_req_make2(struct httpreq **preq, void Curl_http_req_free(struct httpreq *req); -#define HTTP_PSEUDO_METHOD ":method" -#define HTTP_PSEUDO_SCHEME ":scheme" +#define HTTP_PSEUDO_METHOD ":method" +#define HTTP_PSEUDO_SCHEME ":scheme" #define HTTP_PSEUDO_AUTHORITY ":authority" -#define HTTP_PSEUDO_PATH ":path" -#define HTTP_PSEUDO_STATUS ":status" +#define HTTP_PSEUDO_PATH ":path" +#define HTTP_PSEUDO_STATUS ":status" /** * Create the list of HTTP/2 headers which represent the request, diff --git a/lib/http1.c b/lib/http1.c index 098dd7cd64f8..e12dd32c5a06 100644 --- a/lib/http1.c +++ b/lib/http1.c @@ -27,17 +27,12 @@ #ifndef CURL_DISABLE_HTTP #include "urldata.h" -#include #include "http.h" #include "http1.h" #include "urlapi-int.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - -#define H1_MAX_URL_LEN (8*1024) +#define H1_MAX_URL_LEN (8 * 1024) void Curl_h1_req_parse_init(struct h1_req_parser *parser, size_t max_line_len) { @@ -80,63 +75,66 @@ static CURLcode trim_line(struct h1_req_parser *parser, int options) return CURLE_OK; } -static ssize_t detect_line(struct h1_req_parser *parser, - const char *buf, const size_t buflen, - CURLcode *err) +static CURLcode detect_line(struct h1_req_parser *parser, + const uint8_t *buf, const size_t buflen, + size_t *pnread) { - const char *line_end; + const char *line_end; DEBUGASSERT(!parser->line); + *pnread = 0; line_end = memchr(buf, '\n', buflen); - if(!line_end) { - *err = CURLE_AGAIN; - return -1; - } - parser->line = buf; - parser->line_len = line_end - buf + 1; - *err = CURLE_OK; - return (ssize_t)parser->line_len; + if(!line_end) + return CURLE_AGAIN; + parser->line = (const char *)buf; + parser->line_len = line_end - parser->line + 1; + *pnread = parser->line_len; + return CURLE_OK; } -static ssize_t next_line(struct h1_req_parser *parser, - const char *buf, const size_t buflen, int options, - CURLcode *err) +static CURLcode next_line(struct h1_req_parser *parser, + const uint8_t *buf, const size_t buflen, int options, + size_t *pnread) { - ssize_t nread = 0; + CURLcode result; + *pnread = 0; if(parser->line) { parser->line = NULL; parser->line_len = 0; curlx_dyn_reset(&parser->scratch); } - nread = detect_line(parser, buf, buflen, err); - if(nread >= 0) { + result = detect_line(parser, buf, buflen, pnread); + if(!result) { if(curlx_dyn_len(&parser->scratch)) { /* append detected line to scratch to have the complete line */ - *err = curlx_dyn_addn(&parser->scratch, parser->line, parser->line_len); - if(*err) - return -1; + result = curlx_dyn_addn(&parser->scratch, parser->line, + parser->line_len); + if(result) + return result; parser->line = curlx_dyn_ptr(&parser->scratch); parser->line_len = curlx_dyn_len(&parser->scratch); } - *err = trim_line(parser, options); - if(*err) - return -1; + result = trim_line(parser, options); + if(result) + return result; } - else if(*err == CURLE_AGAIN) { + else if(result == CURLE_AGAIN) { /* no line end in `buf`, add it to our scratch */ - *err = curlx_dyn_addn(&parser->scratch, (const unsigned char *)buf, - buflen); - nread = (*err) ? -1 : (ssize_t)buflen; + result = curlx_dyn_addn(&parser->scratch, (const unsigned char *)buf, + buflen); + *pnread = buflen; } - return nread; + return result; } static CURLcode start_req(struct h1_req_parser *parser, - const char *scheme_default, int options) + const char *scheme_default, + const char *custom_method, + int options) { - const char *p, *m, *target, *hv, *scheme, *authority, *path; + const char *p, *m, *target, *hv, *scheme, *authority, *path; size_t m_len, target_len, hv_len, scheme_len, authority_len, path_len; size_t i; CURLU *url = NULL; @@ -144,9 +142,15 @@ static CURLcode start_req(struct h1_req_parser *parser, DEBUGASSERT(!parser->req); /* line must match: "METHOD TARGET HTTP_VERSION" */ - p = memchr(parser->line, ' ', parser->line_len); - if(!p || p == parser->line) - goto out; + if(custom_method && custom_method[0] && + !strncmp(custom_method, parser->line, strlen(custom_method))) { + p = parser->line + strlen(custom_method); + } + else { + p = memchr(parser->line, ' ', parser->line_len); + if(!p || p == parser->line) + goto out; + } m = parser->line; m_len = p - parser->line; @@ -222,8 +226,8 @@ static CURLcode start_req(struct h1_req_parser *parser, result = CURLE_OUT_OF_MEMORY; goto out; } - url_options = (CURLU_NON_SUPPORT_SCHEME| - CURLU_PATH_AS_IS| + url_options = (CURLU_NON_SUPPORT_SCHEME | + CURLU_PATH_AS_IS | CURLU_NO_DEFAULT_PORT); if(!(options & H1_PARSE_OPT_STRICT)) url_options |= CURLU_ALLOW_SPACE; @@ -256,28 +260,28 @@ static CURLcode start_req(struct h1_req_parser *parser, return result; } -ssize_t Curl_h1_req_parse_read(struct h1_req_parser *parser, - const char *buf, size_t buflen, - const char *scheme_default, int options, - CURLcode *err) +CURLcode Curl_h1_req_parse_read(struct h1_req_parser *parser, + const uint8_t *buf, size_t buflen, + const char *scheme_default, + const char *custom_method, + int options, size_t *pnread) { - ssize_t nread = 0, n; + CURLcode result = CURLE_OK; + size_t nread; - *err = CURLE_OK; + *pnread = 0; while(!parser->done) { - n = next_line(parser, buf, buflen, options, err); - if(n < 0) { - if(*err != CURLE_AGAIN) { - nread = -1; - } - *err = CURLE_OK; + result = next_line(parser, buf, buflen, options, &nread); + if(result) { + if(result == CURLE_AGAIN) + result = CURLE_OK; goto out; } /* Consume this line */ - nread += (size_t)n; - buf += (size_t)n; - buflen -= (size_t)n; + *pnread += nread; + buf += nread; + buflen -= nread; if(!parser->line) { /* consumed bytes, but line not complete */ @@ -285,17 +289,14 @@ ssize_t Curl_h1_req_parse_read(struct h1_req_parser *parser, goto out; } else if(!parser->req) { - *err = start_req(parser, scheme_default, options); - if(*err) { - nread = -1; + result = start_req(parser, scheme_default, custom_method, options); + if(result) goto out; - } } else if(parser->line_len == 0) { /* last, empty line, we are finished */ if(!parser->req) { - *err = CURLE_URL_MALFORMAT; - nread = -1; + result = CURLE_URL_MALFORMAT; goto out; } parser->done = TRUE; @@ -303,17 +304,15 @@ ssize_t Curl_h1_req_parse_read(struct h1_req_parser *parser, /* last chance adjustments */ } else { - *err = Curl_dynhds_h1_add_line(&parser->req->headers, - parser->line, parser->line_len); - if(*err) { - nread = -1; + result = Curl_dynhds_h1_add_line(&parser->req->headers, + parser->line, parser->line_len); + if(result) goto out; - } } } out: - return nread; + return result; } CURLcode Curl_h1_req_write_head(struct httpreq *req, int http_minor, diff --git a/lib/http1.h b/lib/http1.h index b38b32f59115..88bd99798e05 100644 --- a/lib/http1.h +++ b/lib/http1.h @@ -48,10 +48,11 @@ struct h1_req_parser { void Curl_h1_req_parse_init(struct h1_req_parser *parser, size_t max_line_len); void Curl_h1_req_parse_free(struct h1_req_parser *parser); -ssize_t Curl_h1_req_parse_read(struct h1_req_parser *parser, - const char *buf, size_t buflen, - const char *scheme_default, int options, - CURLcode *err); +CURLcode Curl_h1_req_parse_read(struct h1_req_parser *parser, + const uint8_t *buf, size_t buflen, + const char *scheme_default, + const char *custom_method, + int options, size_t *pnread); CURLcode Curl_h1_req_dprint(const struct httpreq *req, struct dynbuf *dbuf); diff --git a/lib/http2.c b/lib/http2.c index 4e2d59ff5187..061c4d67fb98 100644 --- a/lib/http2.c +++ b/lib/http2.c @@ -27,6 +27,7 @@ #if !defined(CURL_DISABLE_HTTP) && defined(USE_NGHTTP2) #include #include + #include "urldata.h" #include "bufq.h" #include "uint-hash.h" @@ -34,30 +35,26 @@ #include "http2.h" #include "http.h" #include "sendf.h" +#include "curl_trc.h" #include "select.h" #include "curlx/base64.h" #include "multiif.h" +#include "progress.h" #include "url.h" #include "urlapi-int.h" #include "cfilters.h" #include "connect.h" -#include "rand.h" -#include "strdup.h" -#include "curlx/strparse.h" #include "transfer.h" +#include "bufref.h" #include "curlx/dynbuf.h" #include "headers.h" -/* The last 3 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - #if (NGHTTP2_VERSION_NUM < 0x010c00) #error too old nghttp2 version, upgrade! #endif #ifdef CURL_DISABLE_VERBOSE_STRINGS -#define nghttp2_session_callbacks_set_error_callback(x,y) +#define nghttp2_session_callbacks_set_error_callback(x, y) #endif #if (NGHTTP2_VERSION_NUM >= 0x010c00) @@ -95,36 +92,9 @@ * is blocked from sending us any data. See #10988 for an issue with this. */ #define HTTP2_HUGE_WINDOW_SIZE (100 * H2_STREAM_WINDOW_SIZE_MAX) -#define H2_SETTINGS_IV_LEN 3 +#define H2_SETTINGS_IV_LEN 3 #define H2_BINSETTINGS_LEN 80 -static size_t populate_settings(nghttp2_settings_entry *iv, - struct Curl_easy *data) -{ - iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; - iv[0].value = Curl_multi_max_concurrent_streams(data->multi); - - iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; - iv[1].value = H2_STREAM_WINDOW_SIZE_INITIAL; - - iv[2].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH; - iv[2].value = data->multi->push_cb != NULL; - - return 3; -} - -static ssize_t populate_binsettings(uint8_t *binsettings, - struct Curl_easy *data) -{ - nghttp2_settings_entry iv[H2_SETTINGS_IV_LEN]; - size_t ivlen; - - ivlen = populate_settings(iv, data); - /* this returns number of bytes it wrote or a negative number on error. */ - return nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN, - iv, ivlen); -} - struct cf_h2_ctx { nghttp2_session *h2; /* The easy handle used in the current filter call, cleared at return */ @@ -137,13 +107,11 @@ struct cf_h2_ctx { struct uint_hash streams; /* hash of `data->mid` to `h2_stream_ctx` */ size_t drain_total; /* sum of all stream's UrlState drain */ + uint32_t initial_win_size; /* current initial window size (settings) */ uint32_t max_concurrent_streams; uint32_t goaway_error; /* goaway error code from server */ int32_t remote_max_sid; /* max id processed by server */ int32_t local_max_sid; /* max id processed by us */ -#ifdef DEBUGBUILD - int32_t stream_win_max; /* max h2 stream window size */ -#endif BIT(initialized); BIT(via_h1_upgrade); BIT(conn_closed); @@ -155,8 +123,7 @@ struct cf_h2_ctx { /* How to access `call_data` from a cf_h2 filter */ #undef CF_CTX_CALL_DATA -#define CF_CTX_CALL_DATA(cf) \ - ((struct cf_h2_ctx *)(cf)->ctx)->call_data +#define CF_CTX_CALL_DATA(cf) ((struct cf_h2_ctx *)(cf)->ctx)->call_data static void h2_stream_hash_free(unsigned int id, void *stream); @@ -166,21 +133,9 @@ static void cf_h2_ctx_init(struct cf_h2_ctx *ctx, bool via_h1_upgrade) Curl_bufq_initp(&ctx->inbufq, &ctx->stream_bufcp, H2_NW_RECV_CHUNKS, 0); Curl_bufq_initp(&ctx->outbufq, &ctx->stream_bufcp, H2_NW_SEND_CHUNKS, 0); curlx_dyn_init(&ctx->scratch, CURL_MAX_HTTP_HEADER); - Curl_uint_hash_init(&ctx->streams, 63, h2_stream_hash_free); + Curl_uint32_hash_init(&ctx->streams, 63, h2_stream_hash_free); ctx->remote_max_sid = 2147483647; ctx->via_h1_upgrade = via_h1_upgrade; -#ifdef DEBUGBUILD - { - const char *p = getenv("CURL_H2_STREAM_WIN_MAX"); - - ctx->stream_win_max = H2_STREAM_WINDOW_SIZE_MAX; - if(p) { - curl_off_t l; - if(!curlx_str_number(&p, &l, INT_MAX)) - ctx->stream_win_max = (int32_t)l; - } - } -#endif ctx->initialized = TRUE; } @@ -191,10 +146,10 @@ static void cf_h2_ctx_free(struct cf_h2_ctx *ctx) Curl_bufq_free(&ctx->outbufq); Curl_bufcp_free(&ctx->stream_bufcp); curlx_dyn_free(&ctx->scratch); - Curl_uint_hash_destroy(&ctx->streams); + Curl_uint32_hash_destroy(&ctx->streams); memset(ctx, 0, sizeof(*ctx)); } - free(ctx); + curlx_free(ctx); } static void cf_h2_ctx_close(struct cf_h2_ctx *ctx) @@ -204,6 +159,60 @@ static void cf_h2_ctx_close(struct cf_h2_ctx *ctx) } } +static uint32_t cf_h2_initial_win_size(struct Curl_easy *data) +{ +#if NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE + /* If the transfer has a rate-limit lower than the default initial + * stream window size, use that. It needs to be at least 8k or servers + * may be unhappy. */ + if(data->progress.dl.rlimit.rate_per_step && + (data->progress.dl.rlimit.rate_per_step < H2_STREAM_WINDOW_SIZE_INITIAL)) + return CURLMAX((uint32_t)data->progress.dl.rlimit.rate_per_step, 8192); +#endif + return H2_STREAM_WINDOW_SIZE_INITIAL; +} + +static size_t populate_settings(nghttp2_settings_entry *iv, + struct Curl_easy *data, + struct cf_h2_ctx *ctx) +{ + iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS; + iv[0].value = Curl_multi_max_concurrent_streams(data->multi); + + iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; + iv[1].value = cf_h2_initial_win_size(data); + if(ctx) + ctx->initial_win_size = iv[1].value; + iv[2].settings_id = NGHTTP2_SETTINGS_ENABLE_PUSH; + iv[2].value = data->multi->push_cb != NULL; + + return 3; +} + +static ssize_t populate_binsettings(uint8_t *binsettings, + struct Curl_easy *data) +{ + nghttp2_settings_entry iv[H2_SETTINGS_IV_LEN]; + size_t ivlen; + + ivlen = populate_settings(iv, data, NULL); + /* this returns number of bytes it wrote or a negative number on error. */ + return nghttp2_pack_settings_payload(binsettings, H2_BINSETTINGS_LEN, + iv, ivlen); +} + +static CURLcode cf_h2_update_settings(struct cf_h2_ctx *ctx, + uint32_t initial_win_size) +{ + nghttp2_settings_entry entry; + entry.settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE; + entry.value = initial_win_size; + if(nghttp2_submit_settings(ctx->h2, NGHTTP2_FLAG_NONE, &entry, 1)) + return CURLE_SEND_ERROR; + ctx->initial_win_size = initial_win_size; + return CURLE_OK; +} + static CURLcode nw_out_flush(struct Curl_cfilter *cf, struct Curl_easy *data); @@ -239,16 +248,16 @@ struct h2_stream_ctx { BIT(write_paused); /* stream write is paused */ }; -#define H2_STREAM_CTX(ctx,data) \ +#define H2_STREAM_CTX(ctx, data) \ ((struct h2_stream_ctx *)( \ - data? Curl_uint_hash_get(&(ctx)->streams, (data)->mid) : NULL)) + data? Curl_uint32_hash_get(&(ctx)->streams, (data)->mid) : NULL)) static struct h2_stream_ctx *h2_stream_ctx_create(struct cf_h2_ctx *ctx) { struct h2_stream_ctx *stream; (void)ctx; - stream = calloc(1, sizeof(*stream)); + stream = curlx_calloc(1, sizeof(*stream)); if(!stream) return NULL; @@ -271,7 +280,7 @@ static void free_push_headers(struct h2_stream_ctx *stream) { size_t i; for(i = 0; i < stream->push_headers_used; i++) - free(stream->push_headers[i]); + curlx_free(stream->push_headers[i]); Curl_safefree(stream->push_headers); stream->push_headers_used = 0; } @@ -282,7 +291,7 @@ static void h2_stream_ctx_free(struct h2_stream_ctx *stream) Curl_h1_req_parse_free(&stream->h1); Curl_dynhds_free(&stream->resp_trailers); free_push_headers(stream); - free(stream); + curlx_free(stream); } static void h2_stream_hash_free(unsigned int id, void *stream) @@ -296,23 +305,17 @@ static void h2_stream_hash_free(unsigned int id, void *stream) static int32_t cf_h2_get_desired_local_win(struct Curl_cfilter *cf, struct Curl_easy *data) { + curl_off_t avail = Curl_rlimit_avail(&data->progress.dl.rlimit, + Curl_pgrs_now(data)); + (void)cf; - if(data->set.max_recv_speed && data->set.max_recv_speed < INT32_MAX) { - /* The transfer should only receive `max_recv_speed` bytes per second. - * We restrict the stream's local window size, so that the server cannot - * send us "too much" at a time. - * This gets less precise the higher the latency. */ - return (int32_t)data->set.max_recv_speed; - } -#ifdef DEBUGBUILD - else { - struct cf_h2_ctx *ctx = cf->ctx; - CURL_TRC_CF(data, cf, "stream_win_max=%d", ctx->stream_win_max); - return ctx->stream_win_max; + if(avail < CURL_OFF_T_MAX) { /* limit in place */ + if(avail <= 0) + return 0; + else if(avail < INT32_MAX) + return (int32_t)avail; } -#else return H2_STREAM_WINDOW_SIZE_MAX; -#endif } static CURLcode cf_h2_update_local_win(struct Curl_cfilter *cf, @@ -376,7 +379,6 @@ static CURLcode cf_h2_update_local_win(struct Curl_cfilter *cf, } #endif /* !NGHTTP2_HAS_SET_LOCAL_WINDOW_SIZE */ - static CURLcode http2_data_setup(struct Curl_cfilter *cf, struct Curl_easy *data, struct h2_stream_ctx **pstream) @@ -396,7 +398,7 @@ static CURLcode http2_data_setup(struct Curl_cfilter *cf, if(!stream) return CURLE_OUT_OF_MEMORY; - if(!Curl_uint_hash_set(&ctx->streams, data->mid, stream)) { + if(!Curl_uint32_hash_set(&ctx->streams, data->mid, stream)) { h2_stream_ctx_free(stream); return CURLE_OUT_OF_MEMORY; } @@ -436,7 +438,7 @@ static void http2_data_done(struct Curl_cfilter *cf, struct Curl_easy *data) } } - Curl_uint_hash_remove(&ctx->streams, data->mid); + Curl_uint32_hash_remove(&ctx->streams, data->mid); } static int h2_client_new(struct Curl_cfilter *cf, @@ -444,8 +446,8 @@ static int h2_client_new(struct Curl_cfilter *cf, { struct cf_h2_ctx *ctx = cf->ctx; nghttp2_option *o; - nghttp2_mem mem = {NULL, Curl_nghttp2_malloc, Curl_nghttp2_free, - Curl_nghttp2_calloc, Curl_nghttp2_realloc}; + nghttp2_mem mem = { NULL, Curl_nghttp2_malloc, Curl_nghttp2_free, + Curl_nghttp2_calloc, Curl_nghttp2_realloc }; int rc = nghttp2_option_new(&o); if(rc) @@ -506,7 +508,7 @@ static CURLcode cf_h2_ctx_open(struct Curl_cfilter *cf, rc = nghttp2_session_callbacks_new(&cbs); if(rc) { - failf(data, "Couldn't initialize nghttp2 callbacks"); + failf(data, "Could not initialize nghttp2 callbacks"); goto out; } @@ -530,7 +532,7 @@ static CURLcode cf_h2_ctx_open(struct Curl_cfilter *cf, /* The nghttp2 session is not yet setup, do it */ rc = h2_client_new(cf, cbs); if(rc) { - failf(data, "Couldn't initialize nghttp2"); + failf(data, "Could not initialize nghttp2"); goto out; } ctx->max_concurrent_streams = DEFAULT_MAX_CONCURRENT_STREAMS; @@ -540,10 +542,12 @@ static CURLcode cf_h2_ctx_open(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]; - ssize_t binlen; /* length of the binsettings data */ + ssize_t rclen; + size_t binlen; /* length of the binsettings data */ + + rclen = populate_binsettings(binsettings, data); - binlen = populate_binsettings(binsettings, data); - if(binlen <= 0) { + if(!curlx_sztouz(rclen, &binlen) || !binlen) { failf(data, "nghttp2 unexpectedly failed on pack_settings_payload"); result = CURLE_FAILED_INIT; goto out; @@ -555,7 +559,7 @@ static CURLcode cf_h2_ctx_open(struct Curl_cfilter *cf, DEBUGASSERT(stream); stream->id = 1; /* queue SETTINGS frame (again) */ - rc = nghttp2_session_upgrade2(ctx->h2, binsettings, (size_t)binlen, + rc = nghttp2_session_upgrade2(ctx->h2, binsettings, binlen, data->state.httpreq == HTTPREQ_HEAD, NULL); if(rc) { @@ -578,7 +582,7 @@ static CURLcode cf_h2_ctx_open(struct Curl_cfilter *cf, nghttp2_settings_entry iv[H2_SETTINGS_IV_LEN]; size_t ivlen; - ivlen = populate_settings(iv, data); + ivlen = populate_settings(iv, data, ctx); rc = nghttp2_submit_settings(ctx->h2, NGHTTP2_FLAG_NONE, iv, ivlen); if(rc) { @@ -628,16 +632,16 @@ static CURLcode h2_process_pending_input(struct Curl_cfilter *cf, { struct cf_h2_ctx *ctx = cf->ctx; const unsigned char *buf; - size_t blen; + size_t blen, nread; ssize_t rv; while(Curl_bufq_peek(&ctx->inbufq, &buf, &blen)) { rv = nghttp2_session_mem_recv(ctx->h2, (const uint8_t *)buf, blen); - if(rv < 0) { + if(!curlx_sztouz(rv, &nread)) { failf(data, "nghttp2 recv error %zd: %s", rv, nghttp2_strerror((int)rv)); return CURLE_HTTP2; } - Curl_bufq_skip(&ctx->inbufq, (size_t)rv); + Curl_bufq_skip(&ctx->inbufq, nread); if(Curl_bufq_is_empty(&ctx->inbufq)) { break; } @@ -714,7 +718,7 @@ static CURLcode http2_send_ping(struct Curl_cfilter *cf, if(rc) { failf(data, "nghttp2_submit_ping() failed: %s(%d)", nghttp2_strerror(rc), rc); - return CURLE_HTTP2; + return CURLE_HTTP2; } rc = nghttp2_session_send(ctx->h2); @@ -797,11 +801,10 @@ static ssize_t send_callback(nghttp2_session *h2, ctx->nw_out_blocked = 1; return NGHTTP2_ERR_WOULDBLOCK; } - return (nwritten > SSIZE_MAX) ? + return (nwritten > SSIZE_MAX) ? NGHTTP2_ERR_CALLBACK_FAILURE : (ssize_t)nwritten; } - /* We pass a pointer to this struct in the push callback, but the contents of the struct are hidden from the user. */ struct curl_pushheaders { @@ -919,10 +922,7 @@ static int set_transfer_url(struct Curl_easy *data, if(rc) return rc; - if(data->state.url_alloc) - free(data->state.url); - data->state.url_alloc = TRUE; - data->state.url = url; + Curl_bufref_set(&data->state.url, url, 0, curl_free); return 0; } @@ -946,7 +946,7 @@ static int push_promise(struct Curl_cfilter *cf, struct h2_stream_ctx *stream; struct h2_stream_ctx *newstream; struct curl_pushheaders heads; - CURLMcode rc; + CURLMcode mresult; CURLcode result; /* clone the parent */ struct Curl_easy *newhandle = h2_duphandle(cf, data); @@ -970,7 +970,7 @@ static int push_promise(struct Curl_cfilter *cf, rv = set_transfer_url(newhandle, &heads); if(rv) { - CURL_TRC_CF(data, cf, "[%d] PUSH_PROMISE, failed to set url -> %d", + CURL_TRC_CF(data, cf, "[%d] PUSH_PROMISE, failed to set URL -> %d", frame->promised_stream_id, rv); discard_newhandle(cf, newhandle); rv = CURL_PUSH_DENY; @@ -998,8 +998,8 @@ static int push_promise(struct Curl_cfilter *cf, /* approved, add to the multi handle for processing. This * assigns newhandle->mid. For the new `mid` we assign the * h2_stream instance and remember the stream_id already known. */ - rc = Curl_multi_add_perform(data->multi, newhandle, cf->conn); - if(rc) { + mresult = Curl_multi_add_perform(data->multi, newhandle, cf->conn); + if(mresult) { infof(data, "failed to add handle to multi"); discard_newhandle(cf, newhandle); rv = CURL_PUSH_DENY; @@ -1212,72 +1212,72 @@ static CURLcode on_stream_frame(struct Curl_cfilter *cf, static int fr_print(const nghttp2_frame *frame, char *buffer, size_t blen) { switch(frame->hd.type) { - case NGHTTP2_DATA: { - return curl_msnprintf(buffer, blen, - "FRAME[DATA, len=%d, eos=%d, padlen=%d]", - (int)frame->hd.length, - !!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM), - (int)frame->data.padlen); - } - case NGHTTP2_HEADERS: { - return curl_msnprintf(buffer, blen, - "FRAME[HEADERS, len=%d, hend=%d, eos=%d]", - (int)frame->hd.length, - !!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS), - !!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM)); - } - case NGHTTP2_PRIORITY: { - return curl_msnprintf(buffer, blen, - "FRAME[PRIORITY, len=%d, flags=%d]", - (int)frame->hd.length, frame->hd.flags); - } - case NGHTTP2_RST_STREAM: { - return curl_msnprintf(buffer, blen, - "FRAME[RST_STREAM, len=%d, flags=%d, error=%u]", - (int)frame->hd.length, frame->hd.flags, - frame->rst_stream.error_code); - } - case NGHTTP2_SETTINGS: { - if(frame->hd.flags & NGHTTP2_FLAG_ACK) { - return curl_msnprintf(buffer, blen, "FRAME[SETTINGS, ack=1]"); - } - return curl_msnprintf(buffer, blen, - "FRAME[SETTINGS, len=%d]", (int)frame->hd.length); - } - case NGHTTP2_PUSH_PROMISE: { - return curl_msnprintf(buffer, blen, - "FRAME[PUSH_PROMISE, len=%d, hend=%d]", - (int)frame->hd.length, - !!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS)); - } - case NGHTTP2_PING: { - return curl_msnprintf(buffer, blen, - "FRAME[PING, len=%d, ack=%d]", - (int)frame->hd.length, - frame->hd.flags&NGHTTP2_FLAG_ACK); - } - case NGHTTP2_GOAWAY: { - char scratch[128]; - size_t s_len = CURL_ARRAYSIZE(scratch); - size_t len = (frame->goaway.opaque_data_len < s_len) ? - frame->goaway.opaque_data_len : s_len-1; - if(len) - memcpy(scratch, frame->goaway.opaque_data, len); - scratch[len] = '\0'; - return curl_msnprintf(buffer, blen, - "FRAME[GOAWAY, error=%d, reason='%s', " - "last_stream=%d]", frame->goaway.error_code, - scratch, frame->goaway.last_stream_id); - } - case NGHTTP2_WINDOW_UPDATE: { - return curl_msnprintf(buffer, blen, - "FRAME[WINDOW_UPDATE, incr=%d]", - frame->window_update.window_size_increment); - } - default: - return curl_msnprintf(buffer, blen, "FRAME[%d, len=%d, flags=%d]", - frame->hd.type, (int)frame->hd.length, - frame->hd.flags); + case NGHTTP2_DATA: { + return curl_msnprintf(buffer, blen, + "FRAME[DATA, len=%d, eos=%d, padlen=%d]", + (int)frame->hd.length, + !!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM), + (int)frame->data.padlen); + } + case NGHTTP2_HEADERS: { + return curl_msnprintf(buffer, blen, + "FRAME[HEADERS, len=%d, hend=%d, eos=%d]", + (int)frame->hd.length, + !!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS), + !!(frame->hd.flags & NGHTTP2_FLAG_END_STREAM)); + } + case NGHTTP2_PRIORITY: { + return curl_msnprintf(buffer, blen, + "FRAME[PRIORITY, len=%d, flags=%d]", + (int)frame->hd.length, frame->hd.flags); + } + case NGHTTP2_RST_STREAM: { + return curl_msnprintf(buffer, blen, + "FRAME[RST_STREAM, len=%d, flags=%d, error=%u]", + (int)frame->hd.length, frame->hd.flags, + frame->rst_stream.error_code); + } + case NGHTTP2_SETTINGS: { + if(frame->hd.flags & NGHTTP2_FLAG_ACK) { + return curl_msnprintf(buffer, blen, "FRAME[SETTINGS, ack=1]"); + } + return curl_msnprintf(buffer, blen, + "FRAME[SETTINGS, len=%d]", (int)frame->hd.length); + } + case NGHTTP2_PUSH_PROMISE: { + return curl_msnprintf(buffer, blen, + "FRAME[PUSH_PROMISE, len=%d, hend=%d]", + (int)frame->hd.length, + !!(frame->hd.flags & NGHTTP2_FLAG_END_HEADERS)); + } + case NGHTTP2_PING: { + return curl_msnprintf(buffer, blen, + "FRAME[PING, len=%d, ack=%d]", + (int)frame->hd.length, + frame->hd.flags & NGHTTP2_FLAG_ACK); + } + case NGHTTP2_GOAWAY: { + char scratch[128]; + size_t s_len = CURL_ARRAYSIZE(scratch); + size_t len = (frame->goaway.opaque_data_len < s_len) ? + frame->goaway.opaque_data_len : s_len - 1; + if(len) + memcpy(scratch, frame->goaway.opaque_data, len); + scratch[len] = '\0'; + return curl_msnprintf(buffer, blen, + "FRAME[GOAWAY, error=%d, reason='%s', " + "last_stream=%d]", frame->goaway.error_code, + scratch, frame->goaway.last_stream_id); + } + case NGHTTP2_WINDOW_UPDATE: { + return curl_msnprintf(buffer, blen, + "FRAME[WINDOW_UPDATE, incr=%d]", + frame->window_update.window_size_increment); + } + default: + return curl_msnprintf(buffer, blen, "FRAME[%d, len=%d, flags=%d]", + frame->hd.type, (int)frame->hd.length, + frame->hd.flags); } } @@ -1293,7 +1293,7 @@ static int on_frame_send(nghttp2_session *session, const nghttp2_frame *frame, if(data && Curl_trc_cf_is_verbose(cf, data)) { char buffer[256]; int len; - len = fr_print(frame, buffer, sizeof(buffer)-1); + len = fr_print(frame, buffer, sizeof(buffer) - 1); buffer[len] = 0; CURL_TRC_CF(data, cf, "[%d] -> %s", frame->hd.stream_id, buffer); } @@ -1321,9 +1321,9 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, if(Curl_trc_cf_is_verbose(cf, data)) { char buffer[256]; int len; - len = fr_print(frame, buffer, sizeof(buffer)-1); + len = fr_print(frame, buffer, sizeof(buffer) - 1); buffer[len] = 0; - CURL_TRC_CF(data, cf, "[%d] <- %s",frame->hd.stream_id, buffer); + CURL_TRC_CF(data, cf, "[%d] <- %s", frame->hd.stream_id, buffer); } #endif /* !CURL_DISABLE_VERBOSE_STRINGS */ @@ -1335,9 +1335,9 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, if(!(frame->hd.flags & NGHTTP2_FLAG_ACK)) { uint32_t max_conn = ctx->max_concurrent_streams; ctx->max_concurrent_streams = nghttp2_session_get_remote_settings( - session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS); + session, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS); ctx->enable_push = nghttp2_session_get_remote_settings( - session, NGHTTP2_SETTINGS_ENABLE_PUSH) != 0; + session, NGHTTP2_SETTINGS_ENABLE_PUSH) != 0; CURL_TRC_CF(data, cf, "[0] MAX_CONCURRENT_STREAMS: %d", ctx->max_concurrent_streams); CURL_TRC_CF(data, cf, "[0] ENABLE_PUSH: %s", @@ -1364,7 +1364,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame, ctx->remote_max_sid = frame->goaway.last_stream_id; if(data) { infof(data, "received GOAWAY, error=%u, last_stream=%u", - ctx->goaway_error, ctx->remote_max_sid); + ctx->goaway_error, ctx->remote_max_sid); Curl_multi_connchanged(data->multi); } break; @@ -1398,7 +1398,7 @@ static int cf_h2_on_invalid_frame_recv(nghttp2_session *session, #ifndef CURL_DISABLE_VERBOSE_STRINGS char buffer[256]; int len; - len = fr_print(frame, buffer, sizeof(buffer)-1); + len = fr_print(frame, buffer, sizeof(buffer) - 1); buffer[len] = 0; failf(data, "[HTTP2] [%d] received invalid frame: %s, error %d: %s", stream_id, buffer, ngerr, nghttp2_strerror(ngerr)); @@ -1435,8 +1435,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags, /* Receiving a Stream ID not in the hash should not happen - unless we have aborted a transfer artificially and there were more data in the pipeline. Silently ignore. */ - CURL_TRC_CF(CF_DATA_CURRENT(cf), cf, "[%d] Data for unknown", - stream_id); + CURL_TRC_CF(CF_DATA_CURRENT(cf), cf, "[%d] Data for unknown", stream_id); /* consumed explicitly as no one will read it */ nghttp2_session_consume(session, stream_id, len); return 0; @@ -1589,7 +1588,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, if(frame->hd.type == NGHTTP2_PUSH_PROMISE) { char *h; - if((namelen == (sizeof(HTTP_PSEUDO_AUTHORITY)-1)) && + if((namelen == (sizeof(HTTP_PSEUDO_AUTHORITY) - 1)) && !strncmp(HTTP_PSEUDO_AUTHORITY, (const char *)name, namelen)) { /* pseudo headers are lower case */ int rc = 0; @@ -1610,15 +1609,15 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, stream_id, NGHTTP2_PROTOCOL_ERROR); rc = NGHTTP2_ERR_CALLBACK_FAILURE; } - free(check); + curlx_free(check); if(rc) return rc; } if(!stream->push_headers) { stream->push_headers_alloc = 10; - stream->push_headers = malloc(stream->push_headers_alloc * - sizeof(char *)); + stream->push_headers = curlx_malloc(stream->push_headers_alloc * + sizeof(char *)); if(!stream->push_headers) return NGHTTP2_ERR_CALLBACK_FAILURE; stream->push_headers_used = 0; @@ -1633,8 +1632,8 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, return NGHTTP2_ERR_CALLBACK_FAILURE; } stream->push_headers_alloc *= 2; - headp = realloc(stream->push_headers, - stream->push_headers_alloc * sizeof(char *)); + headp = curlx_realloc(stream->push_headers, + stream->push_headers_alloc * sizeof(char *)); if(!headp) { free_push_headers(stream); return NGHTTP2_ERR_CALLBACK_FAILURE; @@ -1666,15 +1665,16 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame, memcmp(HTTP_PSEUDO_STATUS, name, namelen) == 0) { /* nghttp2 guarantees :status is received first and only once. */ char buffer[32]; + size_t hlen; result = Curl_http_decode_status(&stream->status_code, (const char *)value, valuelen); if(result) { cf_h2_header_error(cf, data_s, stream, result); return NGHTTP2_ERR_CALLBACK_FAILURE; } - curl_msnprintf(buffer, sizeof(buffer), HTTP_PSEUDO_STATUS ":%u\r", - stream->status_code); - result = Curl_headers_push(data_s, buffer, CURLH_PSEUDO); + hlen = curl_msnprintf(buffer, sizeof(buffer), HTTP_PSEUDO_STATUS ":%u\r", + stream->status_code); + result = Curl_headers_push(data_s, buffer, hlen, CURLH_PSEUDO); if(result) { cf_h2_header_error(cf, data_s, stream, result); return NGHTTP2_ERR_CALLBACK_FAILURE; @@ -1805,17 +1805,17 @@ CURLcode Curl_http2_request_upgrade(struct dynbuf *req, size_t blen; struct SingleRequest *k = &data->req; uint8_t binsettings[H2_BINSETTINGS_LEN]; - ssize_t binlen; /* length of the binsettings data */ + ssize_t rc; + size_t binlen; /* length of the binsettings data */ - binlen = populate_binsettings(binsettings, data); - if(binlen <= 0) { + rc = populate_binsettings(binsettings, data); + if(!curlx_sztouz(rc, &binlen) || !binlen) { failf(data, "nghttp2 unexpectedly failed on pack_settings_payload"); curlx_dyn_free(req); return CURLE_FAILED_INIT; } - result = curlx_base64url_encode((const char *)binsettings, (size_t)binlen, - &base64, &blen); + result = curlx_base64url_encode(binsettings, binlen, &base64, &blen); if(result) { curlx_dyn_free(req); return result; @@ -1827,7 +1827,7 @@ CURLcode Curl_http2_request_upgrade(struct dynbuf *req, "Upgrade: %s\r\n" "HTTP2-Settings: %s\r\n", NGHTTP2_CLEARTEXT_PROTO_VERSION_ID, base64); - free(base64); + curlx_free(base64); k->upgr101 = UPGR101_H2; data->conn->bits.upgrade_in_progress = TRUE; @@ -1895,7 +1895,8 @@ static CURLcode http2_handle_stream_close(struct Curl_cfilter *cf, break; Curl_debug(data, CURLINFO_HEADER_IN, curlx_dyn_ptr(&dbuf), curlx_dyn_len(&dbuf)); - result = Curl_client_write(data, CLIENTWRITE_HEADER|CLIENTWRITE_TRAILER, + result = Curl_client_write(data, + CLIENTWRITE_HEADER | CLIENTWRITE_TRAILER, curlx_dyn_ptr(&dbuf), curlx_dyn_len(&dbuf)); if(result) break; @@ -1962,7 +1963,7 @@ static CURLcode h2_progress_egress(struct Curl_cfilter *cf, if(stream && stream->id > 0 && ((sweight_wanted(data) != sweight_in_effect(data)) || (data->set.priority.exclusive != data->state.priority.exclusive) || - (data->set.priority.parent != data->state.priority.parent)) ) { + (data->set.priority.parent != data->state.priority.parent))) { /* send new weight and/or dependency */ nghttp2_priority_spec pri_spec; @@ -2004,6 +2005,9 @@ static CURLcode stream_recv(struct Curl_cfilter *cf, struct Curl_easy *data, (void)len; *pnread = 0; + if(!stream->xfer_result) + stream->xfer_result = cf_h2_update_local_win(cf, data, stream); + if(stream->xfer_result) { CURL_TRC_CF(data, cf, "[%d] xfer write failed", stream->id); result = stream->xfer_result; @@ -2035,7 +2039,7 @@ static CURLcode h2_progress_ingress(struct Curl_cfilter *cf, size_t nread; if(should_close_session(ctx)) { - CURL_TRC_CF(data, cf, "progress ingress, session is closed"); + CURL_TRC_CF(data, cf, "[0] ingress: session is closed"); return CURLE_HTTP2; } @@ -2092,15 +2096,16 @@ static CURLcode h2_progress_ingress(struct Curl_cfilter *cf, result = h2_process_pending_input(cf, data); if(result) return result; - CURL_TRC_CF(data, cf, "[0] progress ingress: inbufg=%zu", + CURL_TRC_CF(data, cf, "[0] ingress: nw-in buffered %zu", Curl_bufq_len(&ctx->inbufq)); } if(ctx->conn_closed && Curl_bufq_is_empty(&ctx->inbufq)) { - connclose(cf->conn, "GOAWAY received"); + connclose(cf->conn, ctx->rcvd_goaway ? "server closed with GOAWAY" : + "server closed abruptly"); } - CURL_TRC_CF(data, cf, "[0] progress ingress: done"); + CURL_TRC_CF(data, cf, "[0] ingress: done"); return CURLE_OK; } @@ -2174,15 +2179,16 @@ static CURLcode cf_h2_recv(struct Curl_cfilter *cf, struct Curl_easy *data, return result; } -static ssize_t cf_h2_body_send(struct Curl_cfilter *cf, - struct Curl_easy *data, - struct h2_stream_ctx *stream, - const void *buf, size_t blen, bool eos, - CURLcode *err) +static CURLcode cf_h2_body_send(struct Curl_cfilter *cf, + struct Curl_easy *data, + struct h2_stream_ctx *stream, + const void *buf, size_t blen, bool eos, + size_t *pnwritten) { struct cf_h2_ctx *ctx = cf->ctx; - size_t nwritten; + CURLcode result; + *pnwritten = 0; if(stream->closed) { if(stream->resp_hds_complete) { /* Server decided to close the stream after having sent us a final @@ -2194,36 +2200,34 @@ static ssize_t cf_h2_body_send(struct Curl_cfilter *cf, "on closed stream with response", stream->id); if(eos) stream->body_eos = TRUE; - *err = CURLE_OK; - return (ssize_t)blen; + *pnwritten = blen; + return CURLE_OK; } /* Server closed before we got a response, this is an error */ infof(data, "stream %u closed", stream->id); - *err = CURLE_SEND_ERROR; - return -1; + return CURLE_SEND_ERROR; } - *err = Curl_bufq_write(&stream->sendbuf, buf, blen, &nwritten); - if(*err) - return -1; + result = Curl_bufq_write(&stream->sendbuf, buf, blen, pnwritten); + if(result) + return result; - if(eos && (blen == nwritten)) + if(eos && (blen == *pnwritten)) stream->body_eos = TRUE; if(eos || !Curl_bufq_is_empty(&stream->sendbuf)) { /* resume the potentially suspended stream */ int rv = nghttp2_session_resume_data(ctx->h2, stream->id); - if(nghttp2_is_fatal(rv)) { - *err = CURLE_SEND_ERROR; - return -1; - } + if(nghttp2_is_fatal(rv)) + return CURLE_SEND_ERROR; } - return (ssize_t)nwritten; + + return CURLE_OK; } static CURLcode h2_submit(struct h2_stream_ctx **pstream, struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, + const uint8_t *buf, size_t len, bool eos, size_t *pnwritten) { struct cf_h2_ctx *ctx = cf->ctx; @@ -2235,8 +2239,9 @@ static CURLcode h2_submit(struct h2_stream_ctx **pstream, nghttp2_data_provider data_prd; int32_t stream_id; nghttp2_priority_spec pri_spec; - ssize_t nwritten; + size_t nwritten; CURLcode result = CURLE_OK; + uint32_t initial_win_size; *pnwritten = 0; Curl_dynhds_init(&h2_headers, 0, DYN_HTTP_REQUEST); @@ -2245,10 +2250,13 @@ static CURLcode h2_submit(struct h2_stream_ctx **pstream, if(result) goto out; - nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, &result); - if(nwritten < 0) + result = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, + !data->state.http_ignorecustom ? + data->set.str[STRING_CUSTOMREQUEST] : NULL, + 0, &nwritten); + if(result) goto out; - *pnwritten = (size_t)nwritten; + *pnwritten = nwritten; if(!stream->h1.done) { /* need more data */ goto out; @@ -2271,6 +2279,15 @@ static CURLcode h2_submit(struct h2_stream_ctx **pstream, if(!nghttp2_session_check_request_allowed(ctx->h2)) CURL_TRC_CF(data, cf, "send request NOT allowed (via nghttp2)"); + /* Check the initial windows size of the transfer (rate-limits?) and + * send an updated settings on changes from previous value. */ + initial_win_size = cf_h2_initial_win_size(data); + if(initial_win_size != ctx->initial_win_size) { + result = cf_h2_update_settings(ctx, initial_win_size); + if(result) + goto out; + } + switch(data->state.httpreq) { case HTTPREQ_POST: case HTTPREQ_POST_FORM: @@ -2299,7 +2316,7 @@ static CURLcode h2_submit(struct h2_stream_ctx **pstream, size_t acc = 0, i; infof(data, "[HTTP/2] [%d] OPENED stream for %s", - stream_id, data->state.url); + stream_id, Curl_bufref_ptr(&data->state.url)); for(i = 0; i < nheader; ++i) { acc += nva[i].namelen + nva[i].valuelen; @@ -2322,8 +2339,9 @@ static CURLcode h2_submit(struct h2_stream_ctx **pstream, bodylen = len - *pnwritten; if(bodylen || eos) { - ssize_t n = cf_h2_body_send(cf, data, stream, body, bodylen, eos, &result); - if(n >= 0) + size_t n; + result = cf_h2_body_send(cf, data, stream, body, bodylen, eos, &n); + if(!result) *pnwritten += n; else if(result == CURLE_AGAIN) result = CURLE_OK; @@ -2342,13 +2360,12 @@ static CURLcode h2_submit(struct h2_stream_ctx **pstream, } static CURLcode cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, bool eos, + const uint8_t *buf, size_t len, bool eos, size_t *pnwritten) { struct cf_h2_ctx *ctx = cf->ctx; struct h2_stream_ctx *stream = H2_STREAM_CTX(ctx, data); struct cf_call_data save; - ssize_t nwritten; CURLcode result = CURLE_OK, r2; CF_DATA_SAVE(save, cf, data); @@ -2365,21 +2382,19 @@ static CURLcode cf_h2_send(struct Curl_cfilter *cf, struct Curl_easy *data, * being able to flush stream->sendbuf. Make a 0-length write * to trigger flushing again. * If this works, we report to have written `len` bytes. */ + size_t n; DEBUGASSERT(eos); - nwritten = cf_h2_body_send(cf, data, stream, buf, 0, eos, &result); - CURL_TRC_CF(data, cf, "[%d] cf_body_send last CHUNK -> %zd, %d, eos=%d", - stream->id, nwritten, result, eos); - if(nwritten < 0) { + result = cf_h2_body_send(cf, data, stream, buf, 0, eos, &n); + CURL_TRC_CF(data, cf, "[%d] cf_body_send last CHUNK -> %d, %zu, eos=%d", + stream->id, result, n, eos); + if(result) goto out; - } *pnwritten = len; } else { - nwritten = cf_h2_body_send(cf, data, stream, buf, len, eos, &result); - CURL_TRC_CF(data, cf, "[%d] cf_body_send(len=%zu) -> %zd, %d, eos=%d", - stream->id, len, nwritten, result, eos); - if(nwritten >= 0) - *pnwritten = (size_t)nwritten; + result = cf_h2_body_send(cf, data, stream, buf, len, eos, pnwritten); + CURL_TRC_CF(data, cf, "[%d] cf_body_send(len=%zu) -> %d, %zu, eos=%d", + stream->id, len, result, *pnwritten, eos); } /* Call the nghttp2 send loop and flush to write ALL buffered data, @@ -2559,7 +2574,7 @@ static CURLcode cf_h2_connect(struct Curl_cfilter *cf, } /* Send out our SETTINGS and ACKs and such. If that blocks, we - * have it buffered and can count this filter as being connected */ + * have it buffered and can count this filter as being connected */ result = h2_progress_egress(cf, data); if(result && (result != CURLE_AGAIN)) goto out; @@ -2773,7 +2788,7 @@ static CURLcode cf_h2_query(struct Curl_cfilter *cf, CF_DATA_SAVE(save, cf, data); if(!ctx->h2 || !nghttp2_session_check_request_allowed(ctx->h2)) { /* the limit is what we have in use right now */ - effective_max = CONN_ATTACHED(cf->conn); + effective_max = cf->conn->attached_xfers; } else { effective_max = ctx->max_concurrent_streams; @@ -2835,7 +2850,7 @@ static CURLcode http2_cfilter_add(struct Curl_cfilter **pcf, CURLcode result = CURLE_OUT_OF_MEMORY; DEBUGASSERT(data->conn); - ctx = calloc(1, sizeof(*ctx)); + ctx = curlx_calloc(1, sizeof(*ctx)); if(!ctx) goto out; cf_h2_ctx_init(ctx, via_h1_upgrade); @@ -2863,7 +2878,7 @@ static CURLcode http2_cfilter_insert_after(struct Curl_cfilter *cf, CURLcode result = CURLE_OUT_OF_MEMORY; (void)data; - ctx = calloc(1, sizeof(*ctx)); + ctx = curlx_calloc(1, sizeof(*ctx)); if(!ctx) goto out; cf_h2_ctx_init(ctx, via_h1_upgrade); @@ -2946,7 +2961,7 @@ CURLcode Curl_http2_upgrade(struct Curl_easy *data, struct cf_h2_ctx *ctx; CURLcode result; - DEBUGASSERT(Curl_conn_http_version(data, conn) < 20); + DEBUGASSERT(Curl_conn_http_version(data, conn) < 20); result = http2_cfilter_add(&cf, data, conn, sockindex, TRUE); if(result) @@ -3029,7 +3044,6 @@ void *Curl_nghttp2_realloc(void *ptr, size_t size, void *user_data) #else /* CURL_DISABLE_HTTP || !USE_NGHTTP2 */ /* Satisfy external references even if http2 is not compiled in. */ -#include char *curl_pushheader_bynum(struct curl_pushheaders *h, size_t num) { diff --git a/lib/http2.h b/lib/http2.h index 93cc2d44f259..147d7f76d538 100644 --- a/lib/http2.h +++ b/lib/http2.h @@ -65,10 +65,10 @@ extern struct Curl_cftype Curl_cft_nghttp2; #define Curl_http2_may_switch(a) FALSE -#define Curl_http2_request_upgrade(x,y) CURLE_UNSUPPORTED_PROTOCOL -#define Curl_http2_switch(a) CURLE_UNSUPPORTED_PROTOCOL -#define Curl_http2_upgrade(a,b,c,d,e) CURLE_UNSUPPORTED_PROTOCOL -#define Curl_h2_http_1_1_error(x) 0 +#define Curl_http2_request_upgrade(x, y) CURLE_UNSUPPORTED_PROTOCOL +#define Curl_http2_switch(a) CURLE_UNSUPPORTED_PROTOCOL +#define Curl_http2_upgrade(a, b, c, d, e) CURLE_UNSUPPORTED_PROTOCOL +#define Curl_h2_http_1_1_error(x) 0 #endif #endif /* HEADER_CURL_HTTP2_H */ diff --git a/lib/http_aws_sigv4.c b/lib/http_aws_sigv4.c index f592f3844feb..d2493b0b0ead 100644 --- a/lib/http_aws_sigv4.c +++ b/lib/http_aws_sigv4.c @@ -32,19 +32,14 @@ #include "http_aws_sigv4.h" #include "curl_sha256.h" #include "transfer.h" -#include "parsedate.h" -#include "sendf.h" +#include "curl_trc.h" #include "escape.h" #include "curlx/strparse.h" +#include "curlx/timeval.h" +#include "slist.h" #include -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - -#include "slist.h" - #define HMAC_SHA256(k, kl, d, dl, o) \ do { \ result = Curl_hmacit(&Curl_HMAC_SHA256, \ @@ -137,7 +132,7 @@ static void trim_headers(struct curl_slist *head) } /* maximum length for the aws sivg4 parts */ -#define MAX_SIGV4_LEN 64 +#define MAX_SIGV4_LEN 64 #define DATE_HDR_KEY_LEN (MAX_SIGV4_LEN + sizeof("X--Date")) /* string been x-PROVIDER-date:TIMESTAMP, I need +1 for ':' */ @@ -210,12 +205,12 @@ static CURLcode merge_duplicate_headers(struct curl_slist *head) if(result) return result; - free(curr->data); + curlx_free(curr->data); curr->data = curlx_dyn_ptr(&buf); curr->next = next->next; - free(next->data); - free(next); + curlx_free(next->data); + curlx_free(next); } else { curr = curr->next; @@ -269,12 +264,11 @@ static CURLcode make_headers(struct Curl_easy *data, if(fullhost) head = Curl_slist_append_nodup(NULL, fullhost); if(!head) { - free(fullhost); + curlx_free(fullhost); goto fail; } } - if(*content_sha256_header) { tmp_head = curl_slist_append(head, content_sha256_header); if(!tmp_head) @@ -308,13 +302,13 @@ static CURLcode make_headers(struct Curl_easy *data, ; if(!*ptr && ptr != sep + 1) /* a value of whitespace only */ continue; - dupdata = strdup(l->data); + dupdata = curlx_strdup(l->data); if(!dupdata) goto fail; dupdata[sep - l->data] = ':'; tmp_head = Curl_slist_append_nodup(head, dupdata); if(!tmp_head) { - free(dupdata); + curlx_free(dupdata); goto fail; } head = tmp_head; @@ -329,6 +323,8 @@ static CURLcode make_headers(struct Curl_easy *data, goto fail; head = tmp_head; *date_header = curl_maprintf("%s: %s\r\n", date_hdr_key, timestamp); + if(!*date_header) + goto fail; } else { const char *value; @@ -403,14 +399,14 @@ static CURLcode make_headers(struct Curl_easy *data, #define CONTENT_SHA256_KEY_LEN (MAX_SIGV4_LEN + sizeof("X--Content-Sha256")) /* add 2 for ": " between header name and value */ -#define CONTENT_SHA256_HDR_LEN (CONTENT_SHA256_KEY_LEN + 2 + \ - SHA256_HEX_LENGTH) +#define CONTENT_SHA256_HDR_LEN (CONTENT_SHA256_KEY_LEN + 2 + SHA256_HEX_LENGTH) /* try to parse a payload hash from the content-sha256 header */ static const char *parse_content_sha_hdr(struct Curl_easy *data, const char *provider1, size_t plen, - size_t *value_len) { + size_t *value_len) +{ char key[CONTENT_SHA256_KEY_LEN]; size_t key_len; const char *value; @@ -431,7 +427,7 @@ static const char *parse_content_sha_hdr(struct Curl_easy *data, curlx_str_passblanks(&value); len = strlen(value); - while(len > 0 && ISBLANK(value[len-1])) + while(len > 0 && ISBLANK(value[len - 1])) --len; *value_len = len; @@ -451,7 +447,7 @@ static CURLcode calc_payload_hash(struct Curl_easy *data, else post_data_len = (size_t)data->set.postfieldsize; } - result = Curl_sha256it(sha_hash, (const unsigned char *) post_data, + result = Curl_sha256it(sha_hash, (const unsigned char *)post_data, post_data_len); if(!result) sha256_to_hex(sha_hex, sha_hash); @@ -532,7 +528,6 @@ static int compare_func(const void *a, const void *b) compare = strcmp(curlx_dyn_ptr(&aa->value), curlx_dyn_ptr(&bb->value)); return compare; - } UNITTEST CURLcode canon_path(const char *q, size_t len, @@ -574,14 +569,13 @@ UNITTEST CURLcode canon_query(const char *query, struct dynbuf *dq) if(!query) return result; - result = split_to_dyn_array(query, &query_array[0], - &num_query_components); + result = split_to_dyn_array(query, &query_array[0], &num_query_components); if(result) { goto fail; } /* Create list of pairs, each pair containing an encoded query - * component */ + * component */ for(index = 0; index < num_query_components; index++) { const char *in_key; @@ -601,8 +595,8 @@ UNITTEST CURLcode canon_query(const char *query, struct dynbuf *dq) in_key_len = offset - in_key; } - curlx_dyn_init(&encoded_query_array[index].key, query_part_len*3 + 1); - curlx_dyn_init(&encoded_query_array[index].value, query_part_len*3 + 1); + curlx_dyn_init(&encoded_query_array[index].key, query_part_len * 3 + 1); + curlx_dyn_init(&encoded_query_array[index].value, query_part_len * 3 + 1); counted_query_components++; /* Decode/encode the key */ @@ -674,8 +668,8 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data) const char *line; struct Curl_str provider0; struct Curl_str provider1; - struct Curl_str region = { NULL, 0}; - struct Curl_str service = { NULL, 0}; + struct Curl_str region = { NULL, 0 }; + struct Curl_str service = { NULL, 0 }; const char *hostname = conn->host.name; time_t clock; struct tm tm; @@ -699,8 +693,8 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data) char *str_to_sign = NULL; const char *user = data->state.aptr.user ? data->state.aptr.user : ""; char *secret = NULL; - unsigned char sign0[CURL_SHA256_DIGEST_LENGTH] = {0}; - unsigned char sign1[CURL_SHA256_DIGEST_LENGTH] = {0}; + unsigned char sign0[CURL_SHA256_DIGEST_LENGTH] = { 0 }; + unsigned char sign1[CURL_SHA256_DIGEST_LENGTH] = { 0 }; char *auth_headers = NULL; if(data->set.path_as_is) { @@ -784,7 +778,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data) /* AWS S3 requires a x-amz-content-sha256 header, and supports special * values like UNSIGNED-PAYLOAD */ bool sign_as_s3 = curlx_str_casecompare(&provider0, "aws") && - curlx_str_casecompare(&service, "s3"); + curlx_str_casecompare(&service, "s3"); if(sign_as_s3) result = calc_s3_payload_hash(data, httpreq, curlx_str(&provider1), @@ -811,7 +805,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data) #else clock = time(NULL); #endif - result = Curl_gmtime(clock, &tm); + result = curlx_gmtime(clock, &tm); if(result) { goto fail; } @@ -866,7 +860,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data) goto fail; infof(data, "aws_sigv4: Canonical request (enclosed in []) - [%s]", - canonical_request); + canonical_request); request_type = curl_maprintf("%.*s4_request", (int)curlx_strlen(&provider0), @@ -887,7 +881,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data) if(!credential_scope) goto fail; - if(Curl_sha256it(sha_hash, (unsigned char *) canonical_request, + if(Curl_sha256it(sha_hash, (unsigned char *)canonical_request, strlen(canonical_request))) goto fail; @@ -914,7 +908,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data) curlx_strlen(&provider0)); infof(data, "aws_sigv4: String to sign (enclosed in []) - [%s]", - str_to_sign); + str_to_sign); secret = curl_maprintf("%.*s4%s", (int)curlx_strlen(&provider0), curlx_str(&provider0), data->state.aptr.passwd ? @@ -962,7 +956,7 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data) Curl_strntoupper(&auth_headers[sizeof("Authorization: ") - 1], curlx_str(&provider0), curlx_strlen(&provider0)); - free(data->state.aptr.userpwd); + curlx_free(data->state.aptr.userpwd); data->state.aptr.userpwd = auth_headers; data->state.authhost.done = TRUE; result = CURLE_OK; @@ -972,18 +966,18 @@ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data) curlx_dyn_free(&canonical_path); curlx_dyn_free(&canonical_headers); curlx_dyn_free(&signed_headers); - free(canonical_request); - free(request_type); - free(credential_scope); - free(str_to_sign); - free(secret); - free(date_header); + curlx_free(canonical_request); + curlx_free(request_type); + curlx_free(credential_scope); + curlx_free(str_to_sign); + curlx_free(secret); + curlx_free(date_header); return result; } /* -* Frees all allocated strings in a dynbuf pair array, and the dynbuf itself -*/ + * Frees all allocated strings in a dynbuf pair array, and the dynbuf itself + */ static void pair_array_free(struct pair *pair_array, size_t num_elements) { @@ -993,12 +987,11 @@ static void pair_array_free(struct pair *pair_array, size_t num_elements) curlx_dyn_free(&pair_array[index].key); curlx_dyn_free(&pair_array[index].value); } - } /* -* Frees all allocated strings in a split dynbuf, and the dynbuf itself -*/ + * Frees all allocated strings in a split dynbuf, and the dynbuf itself + */ static void dyn_array_free(struct dynbuf *db, size_t num_elements) { @@ -1009,10 +1002,10 @@ static void dyn_array_free(struct dynbuf *db, size_t num_elements) } /* -* Splits source string by SPLIT_BY, and creates an array of dynbuf in db. -* db is initialized by this function. -* Caller is responsible for freeing the array elements with dyn_array_free -*/ + * Splits source string by SPLIT_BY, and creates an array of dynbuf in db. + * db is initialized by this function. + * Caller is responsible for freeing the array elements with dyn_array_free + */ #define SPLIT_BY '&' @@ -1034,8 +1027,7 @@ static CURLcode split_to_dyn_array(const char *source, if(source[pos] == SPLIT_BY) { if(segment_length) { curlx_dyn_init(&db[index], segment_length + 1); - result = curlx_dyn_addn(&db[index], &source[start], - segment_length); + result = curlx_dyn_addn(&db[index], &source[start], segment_length); if(result) goto fail; @@ -1066,7 +1058,6 @@ static CURLcode split_to_dyn_array(const char *source, return result; } - static bool is_reserved_char(const char c) { return (ISALNUM(c) || ISURLPUNTCS(c)); @@ -1093,7 +1084,6 @@ static CURLcode uri_encode_path(struct Curl_str *original_path, return CURLE_OK; } - static CURLcode encode_query_component(char *component, size_t len, struct dynbuf *db) { @@ -1118,8 +1108,8 @@ static CURLcode encode_query_component(char *component, size_t len, } /* -* Populates a dynbuf containing url_encode(url_decode(in)) -*/ + * Populates a dynbuf containing url_encode(url_decode(in)) + */ static CURLcode http_aws_decode_encode(const char *in, size_t in_len, struct dynbuf *out) @@ -1139,10 +1129,10 @@ static CURLcode http_aws_decode_encode(const char *in, size_t in_len, static bool should_urlencode(struct Curl_str *service_name) { /* - * These services require unmodified (not additionally url encoded) URL + * These services require unmodified (not additionally URL-encoded) URL * paths. * should_urlencode == true is equivalent to should_urlencode_uri_path - * from the AWS SDK. Urls are already normalized by the curl url parser + * from the AWS SDK. Urls are already normalized by the curl URL parser */ if(curlx_str_cmp(service_name, "s3") || diff --git a/lib/http_aws_sigv4.h b/lib/http_aws_sigv4.h index 9747c948a69d..25009c680948 100644 --- a/lib/http_aws_sigv4.h +++ b/lib/http_aws_sigv4.h @@ -24,17 +24,16 @@ * ***************************************************************************/ #include "curl_setup.h" + #include "curlx/dynbuf.h" #include "urldata.h" -#include "curlx/strparse.h" /* this is for creating aws_sigv4 header output */ CURLcode Curl_output_aws_sigv4(struct Curl_easy *data); #ifdef UNITTESTS UNITTEST CURLcode canon_path(const char *q, size_t len, - struct dynbuf *new_path, - bool normalize); + struct dynbuf *new_path, bool normalize); UNITTEST CURLcode canon_query(const char *query, struct dynbuf *dq); #endif diff --git a/lib/http_chunks.c b/lib/http_chunks.c index 005d34e7b905..a12d2dce72c8 100644 --- a/lib/http_chunks.c +++ b/lib/http_chunks.c @@ -30,15 +30,9 @@ #include "curl_trc.h" #include "sendf.h" /* for the client write stuff */ #include "curlx/dynbuf.h" -#include "content_encoding.h" #include "http.h" #include "multiif.h" #include "curlx/strparse.h" -#include "curlx/warnless.h" - -/* The last #include files should be: */ -#include "curl_memory.h" -#include "memdebug.h" /* * Chunk format (simplified): @@ -361,7 +355,6 @@ static CURLcode httpchunk_readwrite(struct Curl_easy *data, case CHUNK_FAILED: return CURLE_RECV_ERROR; } - } return CURLE_OK; } @@ -532,8 +525,7 @@ static CURLcode add_last_chunk(struct Curl_easy *data, continue; } - result = Curl_bufq_cwrite(&ctx->chunkbuf, tr->data, - strlen(tr->data), &n); + result = Curl_bufq_cwrite(&ctx->chunkbuf, tr->data, strlen(tr->data), &n); if(!result) result = Curl_bufq_cwrite(&ctx->chunkbuf, STRCONST("\r\n"), &n); if(result) diff --git a/lib/http_chunks.h b/lib/http_chunks.h index b84e479fcd61..d8e5982e6d87 100644 --- a/lib/http_chunks.h +++ b/lib/http_chunks.h @@ -23,6 +23,7 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ +#include "curl_setup.h" #ifndef CURL_DISABLE_HTTP diff --git a/lib/http_digest.c b/lib/http_digest.c index 097c81fd716a..34aba0e3ba2f 100644 --- a/lib/http_digest.c +++ b/lib/http_digest.c @@ -32,10 +32,6 @@ #include "http_digest.h" #include "curlx/strparse.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - /* Test example headers: WWW-Authenticate: Digest realm="testrealm", nonce="1053604598" @@ -152,20 +148,20 @@ CURLcode Curl_output_digest(struct Curl_easy *data, } } if(!tmp) - path = (unsigned char *)strdup((const char *) uripath); + path = (unsigned char *)curlx_strdup((const char *)uripath); if(!path) return CURLE_OUT_OF_MEMORY; result = Curl_auth_create_digest_http_message(data, userp, passwdp, request, path, digest, &response, &len); - free(path); + curlx_free(path); if(result) return result; *allocuserpwd = curl_maprintf("%sAuthorization: Digest %s\r\n", proxy ? "Proxy-" : "", response); - free(response); + curlx_free(response); if(!*allocuserpwd) return CURLE_OUT_OF_MEMORY; diff --git a/lib/http_digest.h b/lib/http_digest.h index 5f797310fd9c..46cffb0bda19 100644 --- a/lib/http_digest.h +++ b/lib/http_digest.h @@ -23,6 +23,7 @@ * SPDX-License-Identifier: curl * ***************************************************************************/ + #include "curl_setup.h" #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_DIGEST_AUTH) diff --git a/lib/http_negotiate.c b/lib/http_negotiate.c index 8a19c1ad8738..a8e715a7b9f8 100644 --- a/lib/http_negotiate.c +++ b/lib/http_negotiate.c @@ -28,16 +28,12 @@ #include "urldata.h" #include "cfilters.h" -#include "sendf.h" +#include "curl_trc.h" #include "http_negotiate.h" #include "vauth/vauth.h" #include "vtls/vtls.h" #include "curlx/strparse.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - static void http_auth_nego_reset(struct connectdata *conn, struct negotiatedata *neg_ctx, @@ -51,7 +47,6 @@ static void http_auth_nego_reset(struct connectdata *conn, Curl_auth_cleanup_spnego(neg_ctx); } - CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn, bool proxy, const char *header) { @@ -124,12 +119,12 @@ CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn, neg_ctx->sslContext = conn->sslContext; #endif /* Check if the connection is using SSL and get the channel binding data */ -#ifdef HAVE_GSSAPI +#ifdef GSS_C_CHANNEL_BOUND_FLAG #ifdef USE_SSL curlx_dyn_init(&neg_ctx->channel_binding_data, SSL_CB_MAX_SIZE + 1); if(Curl_conn_is_ssl(conn, FIRSTSOCKET)) { - result = Curl_ssl_get_channel_binding( - data, FIRSTSOCKET, &neg_ctx->channel_binding_data); + result = Curl_ssl_get_channel_binding(data, FIRSTSOCKET, + &neg_ctx->channel_binding_data); if(result) { http_auth_nego_reset(conn, neg_ctx, proxy); return result; @@ -138,13 +133,13 @@ CURLcode Curl_input_negotiate(struct Curl_easy *data, struct connectdata *conn, #else curlx_dyn_init(&neg_ctx->channel_binding_data, 1); #endif /* USE_SSL */ -#endif /* HAVE_GSSAPI */ +#endif /* GSS_C_CHANNEL_BOUND_FLAG */ /* Initialize the security context and decode our challenge */ result = Curl_auth_decode_spnego_message(data, userp, passwdp, service, host, header, neg_ctx); -#ifdef HAVE_GSSAPI +#ifdef GSS_C_CHANNEL_BOUND_FLAG curlx_dyn_free(&neg_ctx->channel_binding_data); #endif @@ -223,16 +218,16 @@ CURLcode Curl_output_negotiate(struct Curl_easy *data, if(proxy) { #ifndef CURL_DISABLE_PROXY - free(data->state.aptr.proxyuserpwd); + curlx_free(data->state.aptr.proxyuserpwd); data->state.aptr.proxyuserpwd = userp; #endif } else { - free(data->state.aptr.userpwd); + curlx_free(data->state.aptr.userpwd); data->state.aptr.userpwd = userp; } - free(base64); + curlx_free(base64); if(!userp) { return CURLE_OUT_OF_MEMORY; diff --git a/lib/http_negotiate.h b/lib/http_negotiate.h index ad7c43d833ea..8e56e9dea398 100644 --- a/lib/http_negotiate.h +++ b/lib/http_negotiate.h @@ -24,6 +24,8 @@ * ***************************************************************************/ +#include "curl_setup.h" + #if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO) /* this is for Negotiate header input */ diff --git a/lib/http_ntlm.c b/lib/http_ntlm.c index fa375b49bfc6..e5c97269b1d9 100644 --- a/lib/http_ntlm.c +++ b/lib/http_ntlm.c @@ -34,7 +34,7 @@ */ #include "urldata.h" -#include "sendf.h" +#include "curl_trc.h" #include "strcase.h" #include "http_ntlm.h" #include "curl_ntlm_core.h" @@ -49,10 +49,6 @@ #include "curl_sspi.h" #endif -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - CURLcode Curl_input_ntlm(struct Curl_easy *data, bool proxy, /* if proxy or not */ const char *header) /* rest of the www-authenticate: @@ -68,7 +64,7 @@ CURLcode Curl_input_ntlm(struct Curl_easy *data, if(checkprefix("NTLM", header)) { struct ntlmdata *ntlm = Curl_auth_ntlm_get(conn, proxy); if(!ntlm) - return CURLE_FAILED_INIT; + return CURLE_OUT_OF_MEMORY; header += strlen("NTLM"); curlx_str_passblanks(&header); @@ -148,7 +144,7 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy) userp = data->state.aptr.proxyuser; passwdp = data->state.aptr.proxypasswd; service = data->set.str[STRING_PROXY_SERVICE_NAME] ? - data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP"; + data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP"; hostname = conn->http_proxy.host.name; state = &conn->proxy_ntlm_state; authp = &data->state.authproxy; @@ -161,7 +157,7 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy) userp = data->state.aptr.user; passwdp = data->state.aptr.passwd; service = data->set.str[STRING_SERVICE_NAME] ? - data->set.str[STRING_SERVICE_NAME] : "HTTP"; + data->set.str[STRING_SERVICE_NAME] : "HTTP"; hostname = conn->host.name; state = &conn->http_ntlm_state; authp = &data->state.authhost; @@ -180,7 +176,7 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy) #ifdef USE_WINDOWS_SSPI if(!Curl_pSecFn) { - /* not thread safe and leaks - use curl_global_init() to avoid */ + /* not thread-safe and leaks - use curl_global_init() to avoid */ CURLcode err = Curl_sspi_global_init(); if(!Curl_pSecFn) return err; @@ -205,14 +201,13 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy) hostname, ntlm, &ntlmmsg); if(!result) { DEBUGASSERT(Curl_bufref_len(&ntlmmsg) != 0); - result = curlx_base64_encode((const char *) Curl_bufref_ptr(&ntlmmsg), - Curl_bufref_len(&ntlmmsg), &base64, &len); + result = curlx_base64_encode(Curl_bufref_uptr(&ntlmmsg), + Curl_bufref_len(&ntlmmsg), &base64, &len); if(!result) { - free(*allocuserpwd); + curlx_free(*allocuserpwd); *allocuserpwd = curl_maprintf("%sAuthorization: NTLM %s\r\n", - proxy ? "Proxy-" : "", - base64); - free(base64); + proxy ? "Proxy-" : "", base64); + curlx_free(base64); if(!*allocuserpwd) result = CURLE_OUT_OF_MEMORY; } @@ -224,14 +219,13 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy) result = Curl_auth_create_ntlm_type3_message(data, userp, passwdp, ntlm, &ntlmmsg); if(!result && Curl_bufref_len(&ntlmmsg)) { - result = curlx_base64_encode((const char *) Curl_bufref_ptr(&ntlmmsg), + result = curlx_base64_encode(Curl_bufref_uptr(&ntlmmsg), Curl_bufref_len(&ntlmmsg), &base64, &len); if(!result) { - free(*allocuserpwd); + curlx_free(*allocuserpwd); *allocuserpwd = curl_maprintf("%sAuthorization: NTLM %s\r\n", - proxy ? "Proxy-" : "", - base64); - free(base64); + proxy ? "Proxy-" : "", base64); + curlx_free(base64); if(!*allocuserpwd) result = CURLE_OUT_OF_MEMORY; else { diff --git a/lib/http_proxy.c b/lib/http_proxy.c index 845ba2e8f8da..088954f230a3 100644 --- a/lib/http_proxy.c +++ b/lib/http_proxy.c @@ -28,38 +28,22 @@ #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_PROXY) -#include -#include "sendf.h" +#include "curl_trc.h" #include "http.h" #include "url.h" -#include "select.h" -#include "progress.h" #include "cfilters.h" #include "cf-h1-proxy.h" #include "cf-h2-proxy.h" #include "connect.h" -#include "vtls/vtls.h" #include "transfer.h" -#include "multiif.h" #include "vauth/vauth.h" #include "curlx/strparse.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - -static bool hd_name_eq(const char *n1, size_t n1len, - const char *n2, size_t n2len) -{ - return (n1len == n2len) ? curl_strnequal(n1, n2, n1len) : FALSE; -} - static CURLcode dynhds_add_custom(struct Curl_easy *data, bool is_connect, int httpversion, struct dynhds *hds) { struct connectdata *conn = data->conn; - const char *ptr; struct curl_slist *h[2]; struct curl_slist *headers; int numlists = 1; /* by default */ @@ -95,86 +79,82 @@ static CURLcode dynhds_add_custom(struct Curl_easy *data, /* loop through one or two lists */ for(i = 0; i < numlists; i++) { for(headers = h[i]; headers; headers = headers->next) { - const char *name, *value; - size_t namelen, valuelen; + struct Curl_str name; + const char *value = NULL; + size_t valuelen = 0; + const char *ptr = headers->data; /* There are 2 quirks in place for custom headers: * 1. setting only 'name:' to suppress a header from being sent * 2. setting only 'name;' to send an empty (illegal) header */ - ptr = strchr(headers->data, ':'); - if(ptr) { - name = headers->data; - namelen = ptr - headers->data; - ptr++; /* pass the colon */ - curlx_str_passblanks(&ptr); - if(*ptr) { - value = ptr; - valuelen = strlen(value); + if(!curlx_str_cspn(&ptr, &name, ";:")) { + if(!curlx_str_single(&ptr, ':')) { + curlx_str_passblanks(&ptr); + if(*ptr) { + value = ptr; + valuelen = strlen(value); + } + else { + /* quirk #1, suppress this header */ + continue; + } } - else { - /* quirk #1, suppress this header */ - continue; + else if(!curlx_str_single(&ptr, ';')) { + curlx_str_passblanks(&ptr); + if(!*ptr) { + /* quirk #2, send an empty header */ + value = ""; + valuelen = 0; + } + else { + /* this may be used for something else in the future, + * ignore this for now */ + continue; + } } - } - else { - ptr = strchr(headers->data, ';'); - - if(!ptr) { - /* neither : nor ; in provided header value. We seem - * to ignore this silently */ + else + /* neither : nor ; in provided header value. We ignore this + * silently */ continue; - } - - name = headers->data; - namelen = ptr - headers->data; - ptr++; /* pass the semicolon */ - curlx_str_passblanks(&ptr); - if(!*ptr) { - /* quirk #2, send an empty header */ - value = ""; - valuelen = 0; - } - else { - /* this may be used for something else in the future, - * ignore this for now */ - continue; - } } + else + /* no name, move on */ + continue; - DEBUGASSERT(name && value); + DEBUGASSERT(curlx_strlen(&name) && value); if(data->state.aptr.host && /* a Host: header was sent already, do not pass on any custom Host: header as that will produce *two* in the same request! */ - hd_name_eq(name, namelen, STRCONST("Host:"))) + curlx_str_casecompare(&name, "Host")) ; else if(data->state.httpreq == HTTPREQ_POST_FORM && /* this header (extended by formdata.c) is sent later */ - hd_name_eq(name, namelen, STRCONST("Content-Type:"))) + curlx_str_casecompare(&name, "Content-Type")) ; else if(data->state.httpreq == HTTPREQ_POST_MIME && /* this header is sent later */ - hd_name_eq(name, namelen, STRCONST("Content-Type:"))) + curlx_str_casecompare(&name, "Content-Type")) ; else if(data->req.authneg && /* while doing auth neg, do not allow the custom length since we will force length zero then */ - hd_name_eq(name, namelen, STRCONST("Content-Length:"))) + curlx_str_casecompare(&name, "Content-Length")) ; else if((httpversion >= 20) && - hd_name_eq(name, namelen, STRCONST("Transfer-Encoding:"))) - /* HTTP/2 and HTTP/3 do not support chunked requests */ + curlx_str_casecompare(&name, "Transfer-Encoding")) ; - else if((hd_name_eq(name, namelen, STRCONST("Authorization:")) || - hd_name_eq(name, namelen, STRCONST("Cookie:"))) && + /* HTTP/2 and HTTP/3 do not support chunked requests */ + else if((curlx_str_casecompare(&name, "Authorization") || + curlx_str_casecompare(&name, "Cookie")) && /* be careful of sending this potentially sensitive header to other hosts */ !Curl_auth_allowed_to_host(data)) ; else { - CURLcode result; - - result = Curl_dynhds_add(hds, name, namelen, value, valuelen); + CURLcode result = + Curl_dynhds_add(hds, curlx_str(&name), curlx_strlen(&name), + value, valuelen); if(result) return result; } @@ -184,9 +164,9 @@ static CURLcode dynhds_add_custom(struct Curl_easy *data, return CURLE_OK; } -CURLcode Curl_http_proxy_get_destination(struct Curl_cfilter *cf, - const char **phostname, - int *pport, bool *pipv6_ip) +void Curl_http_proxy_get_destination(struct Curl_cfilter *cf, + const char **phostname, + int *pport, bool *pipv6_ip) { DEBUGASSERT(cf); DEBUGASSERT(cf->conn); @@ -209,8 +189,6 @@ CURLcode Curl_http_proxy_get_destination(struct Curl_cfilter *cf, *pipv6_ip = (strchr(*phostname, ':') != NULL); else *pipv6_ip = cf->conn->bits.ipv6_ip; - - return CURLE_OK; } struct cf_proxy_ctx { @@ -231,18 +209,16 @@ CURLcode Curl_http_proxy_create_CONNECT(struct httpreq **preq, CURLcode result; struct httpreq *req = NULL; - result = Curl_http_proxy_get_destination(cf, &hostname, &port, &ipv6_ip); - if(result) - goto out; + Curl_http_proxy_get_destination(cf, &hostname, &port, &ipv6_ip); authority = curl_maprintf("%s%s%s:%d", ipv6_ip ? "[" : "", hostname, - ipv6_ip ?"]" : "", port); + ipv6_ip ? "]" : "", port); if(!authority) { result = CURLE_OUT_OF_MEMORY; goto out; } - result = Curl_http_req_make(&req, "CONNECT", sizeof("CONNECT")-1, + result = Curl_http_req_make(&req, "CONNECT", sizeof("CONNECT") - 1, NULL, 0, authority, strlen(authority), NULL, 0); if(result) @@ -278,7 +254,7 @@ CURLcode Curl_http_proxy_create_CONNECT(struct httpreq **preq, } if(http_version_major == 1 && - !Curl_checkProxyheaders(data, cf->conn, STRCONST("Proxy-Connection"))) { + !Curl_checkProxyheaders(data, cf->conn, STRCONST("Proxy-Connection"))) { result = Curl_dynhds_cadd(&req->headers, "Proxy-Connection", "Keep-Alive"); if(result) goto out; @@ -291,7 +267,7 @@ CURLcode Curl_http_proxy_create_CONNECT(struct httpreq **preq, Curl_http_req_free(req); req = NULL; } - free(authority); + curlx_free(authority); *preq = req; return result; } @@ -407,7 +383,7 @@ static void http_proxy_cf_destroy(struct Curl_cfilter *cf, (void)data; CURL_TRC_CF(data, cf, "destroy"); - free(ctx); + curlx_free(ctx); } static void http_proxy_cf_close(struct Curl_cfilter *cf, @@ -419,10 +395,9 @@ static void http_proxy_cf_close(struct Curl_cfilter *cf, cf->next->cft->do_close(cf->next, data); } - struct Curl_cftype Curl_cft_http_proxy = { "HTTP-PROXY", - CF_TYPE_IP_CONNECT|CF_TYPE_PROXY, + CF_TYPE_IP_CONNECT | CF_TYPE_PROXY, 0, http_proxy_cf_destroy, http_proxy_cf_connect, @@ -446,7 +421,7 @@ CURLcode Curl_cf_http_proxy_insert_after(struct Curl_cfilter *cf_at, CURLcode result; (void)data; - ctx = calloc(1, sizeof(*ctx)); + ctx = curlx_calloc(1, sizeof(*ctx)); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -458,7 +433,7 @@ CURLcode Curl_cf_http_proxy_insert_after(struct Curl_cfilter *cf_at, Curl_conn_cf_insert_after(cf_at, cf); out: - free(ctx); + curlx_free(ctx); return result; } diff --git a/lib/http_proxy.h b/lib/http_proxy.h index e6ab2bacf3bb..7af2ebb284c9 100644 --- a/lib/http_proxy.h +++ b/lib/http_proxy.h @@ -36,9 +36,9 @@ enum Curl_proxy_use { HEADER_CONNECT /* sending CONNECT to a proxy */ }; -CURLcode Curl_http_proxy_get_destination(struct Curl_cfilter *cf, - const char **phostname, - int *pport, bool *pipv6_ip); +void Curl_http_proxy_get_destination(struct Curl_cfilter *cf, + const char **phostname, + int *pport, bool *pipv6_ip); CURLcode Curl_http_proxy_create_CONNECT(struct httpreq **preq, struct Curl_cfilter *cf, @@ -46,7 +46,7 @@ CURLcode Curl_http_proxy_create_CONNECT(struct httpreq **preq, int http_version_major); /* Default proxy timeout in milliseconds */ -#define PROXY_TIMEOUT (3600*1000) +#define PROXY_TIMEOUT (3600 * 1000) CURLcode Curl_cf_http_proxy_query(struct Curl_cfilter *cf, struct Curl_easy *data, diff --git a/lib/httpsrr.c b/lib/httpsrr.c index ae2c106bcef2..7013be5b6665 100644 --- a/lib/httpsrr.c +++ b/lib/httpsrr.c @@ -27,17 +27,12 @@ #ifdef USE_HTTPSRR #include "urldata.h" -#include "curl_addrinfo.h" #include "httpsrr.h" #include "connect.h" -#include "sendf.h" +#include "curl_trc.h" #include "strdup.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - -static CURLcode httpsrr_decode_alpn(const char *cp, size_t len, +static CURLcode httpsrr_decode_alpn(const uint8_t *cp, size_t len, unsigned char *alpns) { /* @@ -49,7 +44,7 @@ static CURLcode httpsrr_decode_alpn(const char *cp, size_t len, int idnum = 0; while(len > 0) { - size_t tlen = (size_t) *cp++; + size_t tlen = *cp++; enum alpnid id; len--; if(tlen > len) @@ -84,7 +79,7 @@ CURLcode Curl_httpsrr_set(struct Curl_easy *data, CURL_TRC_DNS(data, "HTTPS RR MANDATORY left to implement"); break; case HTTPS_RR_CODE_ALPN: /* str_list */ - result = httpsrr_decode_alpn((const char *)val, vlen, hi->alpns); + result = httpsrr_decode_alpn(val, vlen, hi->alpns); CURL_TRC_DNS(data, "HTTPS RR ALPN: %u %u %u %u", hi->alpns[0], hi->alpns[1], hi->alpns[2], hi->alpns[3]); break; @@ -97,7 +92,7 @@ CURLcode Curl_httpsrr_set(struct Curl_easy *data, case HTTPS_RR_CODE_IPV4: /* addr4 list */ if(!vlen || (vlen & 3)) /* the size must be 4-byte aligned */ return CURLE_BAD_FUNCTION_ARGUMENT; - free(hi->ipv4hints); + curlx_free(hi->ipv4hints); hi->ipv4hints = Curl_memdup(val, vlen); if(!hi->ipv4hints) return CURLE_OUT_OF_MEMORY; @@ -107,7 +102,7 @@ CURLcode Curl_httpsrr_set(struct Curl_easy *data, case HTTPS_RR_CODE_ECH: if(!vlen) return CURLE_BAD_FUNCTION_ARGUMENT; - free(hi->echconfiglist); + curlx_free(hi->echconfiglist); hi->echconfiglist = Curl_memdup(val, vlen); if(!hi->echconfiglist) return CURLE_OUT_OF_MEMORY; @@ -117,7 +112,7 @@ CURLcode Curl_httpsrr_set(struct Curl_easy *data, case HTTPS_RR_CODE_IPV6: /* addr6 list */ if(!vlen || (vlen & 15)) /* the size must be 16-byte aligned */ return CURLE_BAD_FUNCTION_ARGUMENT; - free(hi->ipv6hints); + curlx_free(hi->ipv6hints); hi->ipv6hints = Curl_memdup(val, vlen); if(!hi->ipv6hints) return CURLE_OUT_OF_MEMORY; @@ -152,9 +147,9 @@ void Curl_httpsrr_cleanup(struct Curl_https_rrinfo *rrinfo) Curl_safefree(rrinfo->echconfiglist); Curl_safefree(rrinfo->ipv4hints); Curl_safefree(rrinfo->ipv6hints); + Curl_safefree(rrinfo->rrname); } - #ifdef USE_ARES static CURLcode httpsrr_opt(struct Curl_easy *data, @@ -166,7 +161,7 @@ static CURLcode httpsrr_opt(struct Curl_easy *data, unsigned short code; size_t len = 0; - code = ares_dns_rr_get_opt(rr, key, idx, &val, &len); + code = ares_dns_rr_get_opt(rr, key, idx, &val, &len); return Curl_httpsrr_set(data, hinfo, code, val, len); } @@ -188,8 +183,8 @@ CURLcode Curl_httpsrr_from_ares(struct Curl_easy *data, is in ServiceMode */ target = ares_dns_rr_get_str(rr, ARES_RR_HTTPS_TARGET); if(target && target[0]) { - free(hinfo->target); - hinfo->target = strdup(target); + curlx_free(hinfo->target); + hinfo->target = curlx_strdup(target); if(!hinfo->target) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -206,6 +201,7 @@ CURLcode Curl_httpsrr_from_ares(struct Curl_easy *data, } } out: + Curl_safefree(hinfo->rrname); return result; } diff --git a/lib/httpsrr.h b/lib/httpsrr.h index 563d1c8e515b..4259a03262f3 100644 --- a/lib/httpsrr.h +++ b/lib/httpsrr.h @@ -33,11 +33,12 @@ #ifdef USE_HTTPSRR #define CURL_MAXLEN_host_name 253 -#define MAX_HTTPSRR_ALPNS 4 +#define MAX_HTTPSRR_ALPNS 4 struct Curl_easy; struct Curl_https_rrinfo { + char *rrname; /* if NULL, the same as the URL hostname */ /* * Fields from HTTPS RR. The only mandatory fields are priority and target. * See https://datatracker.ietf.org/doc/html/rfc9460#section-14.3.2 diff --git a/lib/idn.c b/lib/idn.c index 7e324db6c4b0..b3618c2de399 100644 --- a/lib/idn.c +++ b/lib/idn.c @@ -22,16 +22,14 @@ * ***************************************************************************/ - /* - * IDN conversions - */ +/* + * IDN conversions + */ #include "curl_setup.h" + #include "urldata.h" #include "idn.h" -#include "sendf.h" -#include "curlx/multibyte.h" -#include "curlx/warnless.h" #ifdef USE_LIBIDN2 #include @@ -45,10 +43,6 @@ #endif #endif /* USE_LIBIDN2 */ -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - /* for macOS and iOS targets */ #ifdef USE_APPLE_IDN #include @@ -92,23 +86,23 @@ static CURLcode mac_idn_to_ascii(const char *in, char **out) { size_t inlen = strlen(in); if(inlen < MAX_HOST_LENGTH) { - char iconv_buffer[MAX_HOST_LENGTH] = {0}; + char iconv_buffer[MAX_HOST_LENGTH] = { 0 }; char *iconv_outptr = iconv_buffer; size_t iconv_outlen = sizeof(iconv_buffer); CURLcode iconv_result = iconv_to_utf8(in, inlen, &iconv_outptr, &iconv_outlen); if(!iconv_result) { UErrorCode err = U_ZERO_ERROR; - UIDNA* idna = uidna_openUTS46( - UIDNA_CHECK_BIDI|UIDNA_NONTRANSITIONAL_TO_ASCII, &err); + UIDNA *idna = uidna_openUTS46( + UIDNA_CHECK_BIDI | UIDNA_NONTRANSITIONAL_TO_ASCII, &err); if(!U_FAILURE(err)) { UIDNAInfo info = UIDNA_INFO_INITIALIZER; - char buffer[MAX_HOST_LENGTH] = {0}; + char buffer[MAX_HOST_LENGTH] = { 0 }; (void)uidna_nameToASCII_UTF8(idna, iconv_buffer, (int)iconv_outlen, buffer, sizeof(buffer) - 1, &info, &err); uidna_close(idna); if(!U_FAILURE(err) && !info.errors) { - *out = strdup(buffer); + *out = curlx_strdup(buffer); if(*out) return CURLE_OK; else @@ -127,16 +121,16 @@ static CURLcode mac_ascii_to_idn(const char *in, char **out) size_t inlen = strlen(in); if(inlen < MAX_HOST_LENGTH) { UErrorCode err = U_ZERO_ERROR; - UIDNA* idna = uidna_openUTS46( - UIDNA_CHECK_BIDI|UIDNA_NONTRANSITIONAL_TO_UNICODE, &err); + UIDNA *idna = uidna_openUTS46( + UIDNA_CHECK_BIDI | UIDNA_NONTRANSITIONAL_TO_UNICODE, &err); if(!U_FAILURE(err)) { UIDNAInfo info = UIDNA_INFO_INITIALIZER; - char buffer[MAX_HOST_LENGTH] = {0}; + char buffer[MAX_HOST_LENGTH] = { 0 }; (void)uidna_nameToUnicodeUTF8(idna, in, -1, buffer, sizeof(buffer) - 1, &info, &err); uidna_close(idna); if(!U_FAILURE(err)) { - *out = strdup(buffer); + *out = curlx_strdup(buffer); if(*out) return CURLE_OK; else @@ -167,24 +161,39 @@ WINBASEAPI int WINAPI IdnToUnicode(DWORD dwFlags, #define IDN_MAX_LENGTH 255 +static char *idn_curlx_convert_wchar_to_UTF8(const wchar_t *str_w, int chars) +{ + char *str_utf8 = NULL; + int bytes = WideCharToMultiByte(CP_UTF8, 0, str_w, chars, NULL, 0, + NULL, NULL); + if(bytes > 0) { + str_utf8 = curlx_malloc(bytes); + if(str_utf8) { + if(WideCharToMultiByte(CP_UTF8, 0, str_w, chars, str_utf8, bytes, + NULL, NULL) == 0) { + curlx_free(str_utf8); + return NULL; + } + } + } + return str_utf8; +} + static CURLcode win32_idn_to_ascii(const char *in, char **out) { - wchar_t *in_w = curlx_convert_UTF8_to_wchar(in); + wchar_t in_w[IDN_MAX_LENGTH]; + int in_w_len; *out = NULL; - if(in_w) { + /* Returned in_w_len includes the null-terminator, which then gets + preserved across the calls that follow, ending up terminating + the buffer returned to the caller. */ + in_w_len = MultiByteToWideChar(CP_UTF8, 0, in, -1, in_w, IDN_MAX_LENGTH); + if(in_w_len) { wchar_t punycode[IDN_MAX_LENGTH]; - int chars = IdnToAscii(0, in_w, (int)(wcslen(in_w) + 1), punycode, - IDN_MAX_LENGTH); - curlx_unicodefree(in_w); - if(chars) { - char *mstr = curlx_convert_wchar_to_UTF8(punycode); - if(mstr) { - *out = strdup(mstr); - curlx_unicodefree(mstr); - if(!*out) - return CURLE_OUT_OF_MEMORY; - } - else + int chars = IdnToAscii(0, in_w, in_w_len, punycode, IDN_MAX_LENGTH); + if(chars > 0) { + *out = idn_curlx_convert_wchar_to_UTF8(punycode, chars); + if(!*out) return CURLE_OUT_OF_MEMORY; } else @@ -196,31 +205,29 @@ static CURLcode win32_idn_to_ascii(const char *in, char **out) return CURLE_OK; } -static CURLcode win32_ascii_to_idn(const char *in, char **output) +static CURLcode win32_ascii_to_idn(const char *in, char **out) { - char *out = NULL; - - wchar_t *in_w = curlx_convert_UTF8_to_wchar(in); - if(in_w) { + wchar_t in_w[IDN_MAX_LENGTH]; + int in_w_len; + *out = NULL; + /* Returned in_w_len includes the null-terminator, which then gets + preserved across the calls that follow, ending up terminating + the buffer returned to the caller. */ + in_w_len = MultiByteToWideChar(CP_UTF8, 0, in, -1, in_w, IDN_MAX_LENGTH); + if(in_w_len) { WCHAR idn[IDN_MAX_LENGTH]; /* stores a UTF-16 string */ - int chars = IdnToUnicode(0, in_w, (int)(wcslen(in_w) + 1), idn, - IDN_MAX_LENGTH); - if(chars) { - /* 'chars' is "the number of characters retrieved" */ - char *mstr = curlx_convert_wchar_to_UTF8(idn); - if(mstr) { - out = strdup(mstr); - curlx_unicodefree(mstr); - if(!out) - return CURLE_OUT_OF_MEMORY; - } + int chars = IdnToUnicode(0, in_w, in_w_len, idn, IDN_MAX_LENGTH); + if(chars > 0) { /* 'chars' is "the number of characters retrieved" */ + *out = idn_curlx_convert_wchar_to_UTF8(idn, chars); + if(!*out) + return CURLE_OUT_OF_MEMORY; } else return CURLE_URL_MALFORMAT; } else return CURLE_URL_MALFORMAT; - *output = out; + return CURLE_OK; } @@ -314,7 +321,7 @@ CURLcode Curl_idn_decode(const char *input, char **output) CURLcode result = idn_decode(input, &d); #ifdef USE_LIBIDN2 if(!result) { - char *c = strdup(d); + char *c = curlx_strdup(d); idn2_free(d); if(c) d = c; @@ -325,7 +332,7 @@ CURLcode Curl_idn_decode(const char *input, char **output) if(!result) { if(!d[0]) { /* ended up zero length, not acceptable */ result = CURLE_URL_MALFORMAT; - free(d); + curlx_free(d); } else *output = d; @@ -339,7 +346,7 @@ CURLcode Curl_idn_encode(const char *puny, char **output) CURLcode result = idn_encode(puny, &d); #ifdef USE_LIBIDN2 if(!result) { - char *c = strdup(d); + char *c = curlx_strdup(d); idn2_free(d); if(c) d = c; diff --git a/lib/if2ip.c b/lib/if2ip.c index 79b0599106de..ef2bfe2b0a48 100644 --- a/lib/if2ip.c +++ b/lib/if2ip.c @@ -55,10 +55,6 @@ #include "curlx/inet_ntop.h" #include "if2ip.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - /* ------------------------------------------------------------------ */ #ifdef USE_IPV6 @@ -66,10 +62,10 @@ unsigned int Curl_ipv6_scope(const struct sockaddr *sa) { if(sa->sa_family == AF_INET6) { - const struct sockaddr_in6 * sa6 = - (const struct sockaddr_in6 *)(const void *) sa; + const struct sockaddr_in6 *sa6 = + (const struct sockaddr_in6 *)(const void *)sa; const unsigned char *b = sa6->sin6_addr.s6_addr; - unsigned short w = (unsigned short) ((b[0] << 8) | b[1]); + unsigned short w = (unsigned short)((b[0] << 8) | b[1]); if((b[0] & 0xFE) == 0xFC) /* Handle ULAs */ return IPV6_SCOPE_UNIQUELOCAL; @@ -107,8 +103,7 @@ if2ip_result_t Curl_if2ip(int af, struct ifaddrs *iface, *head; if2ip_result_t res = IF2IP_NOT_FOUND; -#if defined(USE_IPV6) && \ - !defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) +#if defined(USE_IPV6) && !defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) (void)local_scope_id; #endif @@ -142,7 +137,7 @@ if2ip_result_t Curl_if2ip(int af, #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID /* Include the scope of this interface as part of the address */ scopeid = ((struct sockaddr_in6 *)(void *)iface->ifa_addr) - ->sin6_scope_id; + ->sin6_scope_id; /* If given, scope id should match. */ if(local_scope_id && scopeid != local_scope_id) { @@ -252,15 +247,15 @@ if2ip_result_t Curl_if2ip(int af, const char *interf, char *buf, size_t buf_size) { - (void)af; + (void)af; #ifdef USE_IPV6 - (void)remote_scope; - (void)local_scope_id; + (void)remote_scope; + (void)local_scope_id; #endif - (void)interf; - (void)buf; - (void)buf_size; - return IF2IP_NOT_FOUND; + (void)interf; + (void)buf; + (void)buf_size; + return IF2IP_NOT_FOUND; } #endif diff --git a/lib/if2ip.h b/lib/if2ip.h index b33e41aebd0b..12fdaabd736a 100644 --- a/lib/if2ip.h +++ b/lib/if2ip.h @@ -56,33 +56,33 @@ if2ip_result_t Curl_if2ip(int af, /* Nedelcho Stanev's work-around for SFU 3.0 */ struct ifreq { -#define IFNAMSIZ 16 +#define IFNAMSIZ 16 #define IFHWADDRLEN 6 union { char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */ } ifr_ifrn; - union { - struct sockaddr ifru_addr; - struct sockaddr ifru_broadaddr; - struct sockaddr ifru_netmask; - struct sockaddr ifru_hwaddr; - short ifru_flags; - int ifru_metric; - int ifru_mtu; - } ifr_ifru; + union { + struct sockaddr ifru_addr; + struct sockaddr ifru_broadaddr; + struct sockaddr ifru_netmask; + struct sockaddr ifru_hwaddr; + short ifru_flags; + int ifru_metric; + int ifru_mtu; + } ifr_ifru; }; /* This define exists to avoid an extra #ifdef INTERIX in the C code. */ -#define ifr_name ifr_ifrn.ifrn_name /* interface name */ -#define ifr_addr ifr_ifru.ifru_addr /* address */ +#define ifr_name ifr_ifrn.ifrn_name /* interface name */ +#define ifr_addr ifr_ifru.ifru_addr /* address */ #define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ -#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */ -#define ifr_flags ifr_ifru.ifru_flags /* flags */ -#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ -#define ifr_metric ifr_ifru.ifru_metric /* metric */ -#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ +#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */ +#define ifr_flags ifr_ifru.ifru_flags /* flags */ +#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ +#define ifr_metric ifr_ifru.ifru_metric /* metric */ +#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ #define SIOCGIFADDR _IOW('s', 102, struct ifreq) /* Get if addr */ diff --git a/lib/imap.c b/lib/imap.c index 47757d3f2978..c5da40c4e45e 100644 --- a/lib/imap.c +++ b/lib/imap.c @@ -36,7 +36,6 @@ ***************************************************************************/ #include "curl_setup.h" -#include "curlx/dynbuf.h" #ifndef CURL_DISABLE_IMAP @@ -54,15 +53,15 @@ #include #endif -#include +#include "curlx/dynbuf.h" #include "urldata.h" #include "sendf.h" +#include "curl_trc.h" #include "hostip.h" #include "progress.h" #include "transfer.h" #include "escape.h" #include "http.h" /* for HTTP proxy tunnel stuff */ -#include "socks.h" #include "imap.h" #include "mime.h" #include "curlx/strparse.h" @@ -71,17 +70,10 @@ #include "cfilters.h" #include "connect.h" #include "select.h" -#include "multiif.h" #include "url.h" #include "bufref.h" #include "curl_sasl.h" -#include "curlx/warnless.h" -#include "curl_ctype.h" - -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - +#include "curlx/strcopy.h" /* meta key for storing protocol meta at easy handle */ #define CURL_META_IMAP_EASY "meta:proto:imap:easy" @@ -115,8 +107,8 @@ struct imap_conn { struct SASL sasl; /* SASL-related parameters */ struct dynbuf dyn; /* for the IMAP commands */ char *mailbox; /* The last selected mailbox */ - char *mailbox_uidvalidity; /* UIDVALIDITY parsed from select response */ imapstate state; /* Always use imap.c:state() to change state! */ + unsigned int mb_uidvalidity; /* UIDVALIDITY parsed from select response */ char resptag[5]; /* Response tag to wait for */ unsigned char preftype; /* Preferred authentication type */ unsigned char cmdid; /* Last used command ID */ @@ -125,6 +117,7 @@ struct imap_conn { BIT(tls_supported); /* StartTLS capability supported by server */ BIT(login_disabled); /* LOGIN command disabled by server */ BIT(ir_supported); /* Initial response supported by server */ + BIT(mb_uidvalidity_set); }; /* This IMAP struct is used in the Curl_easy. All IMAP data that is @@ -134,7 +127,6 @@ struct imap_conn { struct IMAP { curl_pp_transfer transfer; char *mailbox; /* Mailbox to select */ - char *uidvalidity; /* UIDVALIDITY to check in select */ char *uid; /* Message UID to fetch */ char *mindex; /* Index in mail box of mail to fetch */ char *section; /* Message SECTION to fetch */ @@ -142,9 +134,10 @@ struct IMAP { char *query; /* Query to search for */ char *custom; /* Custom request */ char *custom_params; /* Parameters for the custom request */ + unsigned int uidvalidity; /* UIDVALIDITY to check in select */ + BIT(uidvalidity_set); }; - /* Local API functions */ static CURLcode imap_regular_transfer(struct Curl_easy *data, struct IMAP *imap, @@ -208,9 +201,9 @@ const struct Curl_handler Curl_handler_imap = { PORT_IMAP, /* defport */ CURLPROTO_IMAP, /* protocol */ CURLPROTO_IMAP, /* family */ - PROTOPT_CLOSEACTION| /* flags */ - PROTOPT_URLOPTIONS| - PROTOPT_SSL_REUSE + PROTOPT_CLOSEACTION | /* flags */ + PROTOPT_URLOPTIONS | PROTOPT_SSL_REUSE | + PROTOPT_CONN_REUSE }; #ifdef USE_SSL @@ -241,7 +234,7 @@ const struct Curl_handler Curl_handler_imaps = { CURLPROTO_IMAPS, /* protocol */ CURLPROTO_IMAP, /* family */ PROTOPT_CLOSEACTION | PROTOPT_SSL | /* flags */ - PROTOPT_URLOPTIONS + PROTOPT_URLOPTIONS | PROTOPT_CONN_REUSE }; #endif @@ -349,46 +342,46 @@ static bool imap_endofresp(struct Curl_easy *data, struct connectdata *conn, /* Do we have an untagged command response? */ if(len >= 2 && !memcmp("* ", line, 2)) { switch(imapc->state) { - /* States which are interested in untagged responses */ - case IMAP_CAPABILITY: - if(!imap_matchresp(line, len, "CAPABILITY")) - return FALSE; - break; - - case IMAP_LIST: - if((!imap->custom && !imap_matchresp(line, len, "LIST")) || - (imap->custom && !imap_matchresp(line, len, imap->custom) && - (!curl_strequal(imap->custom, "STORE") || - !imap_matchresp(line, len, "FETCH")) && - !curl_strequal(imap->custom, "SELECT") && - !curl_strequal(imap->custom, "EXAMINE") && - !curl_strequal(imap->custom, "SEARCH") && - !curl_strequal(imap->custom, "EXPUNGE") && - !curl_strequal(imap->custom, "LSUB") && - !curl_strequal(imap->custom, "UID") && - !curl_strequal(imap->custom, "GETQUOTAROOT") && - !curl_strequal(imap->custom, "NOOP"))) - return FALSE; - break; + /* States which are interested in untagged responses */ + case IMAP_CAPABILITY: + if(!imap_matchresp(line, len, "CAPABILITY")) + return FALSE; + break; - case IMAP_SELECT: - /* SELECT is special in that its untagged responses do not have a - common prefix so accept anything! */ - break; + case IMAP_LIST: + if((!imap->custom && !imap_matchresp(line, len, "LIST")) || + (imap->custom && !imap_matchresp(line, len, imap->custom) && + (!curl_strequal(imap->custom, "STORE") || + !imap_matchresp(line, len, "FETCH")) && + !curl_strequal(imap->custom, "SELECT") && + !curl_strequal(imap->custom, "EXAMINE") && + !curl_strequal(imap->custom, "SEARCH") && + !curl_strequal(imap->custom, "EXPUNGE") && + !curl_strequal(imap->custom, "LSUB") && + !curl_strequal(imap->custom, "UID") && + !curl_strequal(imap->custom, "GETQUOTAROOT") && + !curl_strequal(imap->custom, "NOOP"))) + return FALSE; + break; - case IMAP_FETCH: - if(!imap_matchresp(line, len, "FETCH")) - return FALSE; - break; + case IMAP_SELECT: + /* SELECT is special in that its untagged responses do not have a + common prefix so accept anything! */ + break; - case IMAP_SEARCH: - if(!imap_matchresp(line, len, "SEARCH")) - return FALSE; - break; + case IMAP_FETCH: + if(!imap_matchresp(line, len, "FETCH")) + return FALSE; + break; - /* Ignore other untagged responses */ - default: + case IMAP_SEARCH: + if(!imap_matchresp(line, len, "SEARCH")) return FALSE; + break; + + /* Ignore other untagged responses */ + default: + return FALSE; } *resp = '*'; @@ -402,16 +395,16 @@ static bool imap_endofresp(struct Curl_easy *data, struct connectdata *conn, if(!imap->custom && ((len == 3 && line[0] == '+') || (len >= 2 && !memcmp("+ ", line, 2)))) { switch(imapc->state) { - /* States which are interested in continuation responses */ - case IMAP_AUTHENTICATE: - case IMAP_APPEND: - *resp = '+'; - break; + /* States which are interested in continuation responses */ + case IMAP_AUTHENTICATE: + case IMAP_APPEND: + *resp = '+'; + break; - default: - failf(data, "Unexpected continuation response"); - *resp = -1; - break; + default: + failf(data, "Unexpected continuation response"); + *resp = -1; + break; } return TRUE; @@ -473,7 +466,7 @@ static void imap_state(struct Curl_easy *data, { #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) /* for debug purposes */ - static const char * const names[]={ + static const char * const names[] = { "STOP", "SERVERGREET", "CAPABILITY", @@ -572,8 +565,8 @@ static CURLcode imap_perform_upgrade_tls(struct Curl_easy *data, result, ssldone)); if(!result && ssldone) { imapc->ssldone = ssldone; - /* perform CAPA now, changes imapc->state out of IMAP_UPGRADETLS */ - result = imap_perform_capability(data, imapc); + /* perform CAPA now, changes imapc->state out of IMAP_UPGRADETLS */ + result = imap_perform_capability(data, imapc); } out: return result; @@ -615,8 +608,8 @@ static CURLcode imap_perform_login(struct Curl_easy *data, result = imap_sendf(data, imapc, "LOGIN %s %s", user ? user : "", passwd ? passwd : ""); - free(user); - free(passwd); + curlx_free(user); + curlx_free(passwd); if(!result) imap_state(data, imapc, IMAP_LOGIN); @@ -638,7 +631,7 @@ static CURLcode imap_perform_authenticate(struct Curl_easy *data, struct imap_conn *imapc = Curl_conn_meta_get(data->conn, CURL_META_IMAP_CONN); CURLcode result = CURLE_OK; - const char *ir = (const char *) Curl_bufref_ptr(initresp); + const char *ir = Curl_bufref_ptr(initresp); if(!imapc) return CURLE_FAILED_INIT; @@ -670,8 +663,7 @@ static CURLcode imap_continue_authenticate(struct Curl_easy *data, (void)mech; if(!imapc) return CURLE_FAILED_INIT; - return Curl_pp_sendf(data, &imapc->pp, - "%s", (const char *) Curl_bufref_ptr(resp)); + return Curl_pp_sendf(data, &imapc->pp, "%s", Curl_bufref_ptr(resp)); } /*********************************************************************** @@ -749,14 +741,14 @@ static CURLcode imap_perform_list(struct Curl_easy *data, else { /* Make sure the mailbox is in the correct atom format if necessary */ char *mailbox = imap->mailbox ? imap_atom(imap->mailbox, TRUE) - : strdup(""); + : curlx_strdup(""); if(!mailbox) return CURLE_OUT_OF_MEMORY; /* Send the LIST command */ result = imap_sendf(data, imapc, "LIST \"%s\" *", mailbox); - free(mailbox); + curlx_free(mailbox); } if(!result) @@ -780,7 +772,6 @@ static CURLcode imap_perform_select(struct Curl_easy *data, /* Invalidate old information as we are switching mailboxes */ Curl_safefree(imapc->mailbox); - Curl_safefree(imapc->mailbox_uidvalidity); /* Check we have a mailbox */ if(!imap->mailbox) { @@ -796,7 +787,7 @@ static CURLcode imap_perform_select(struct Curl_easy *data, /* Send the SELECT command */ result = imap_sendf(data, imapc, "SELECT %s", mailbox); - free(mailbox); + curlx_free(mailbox); if(!result) imap_state(data, imapc, IMAP_SELECT); @@ -946,7 +937,7 @@ static CURLcode imap_perform_append(struct Curl_easy *data, cleanup: curlx_dyn_free(&flags); - free(mailbox); + curlx_free(mailbox); if(!result) imap_state(data, imapc, IMAP_APPEND); @@ -1051,24 +1042,24 @@ static CURLcode imap_state_capability_resp(struct Curl_easy *data, /* Extract the word */ for(wordlen = 0; line[wordlen] && line[wordlen] != ' ' && - line[wordlen] != '\t' && line[wordlen] != '\r' && - line[wordlen] != '\n';) + line[wordlen] != '\t' && line[wordlen] != '\r' && + line[wordlen] != '\n';) wordlen++; /* Does the server support the STARTTLS capability? */ - if(wordlen == 8 && !memcmp(line, "STARTTLS", 8)) + if(wordlen == 8 && curl_strnequal(line, "STARTTLS", 8)) imapc->tls_supported = TRUE; /* Has the server explicitly disabled clear text authentication? */ - else if(wordlen == 13 && !memcmp(line, "LOGINDISABLED", 13)) + else if(wordlen == 13 && curl_strnequal(line, "LOGINDISABLED", 13)) imapc->login_disabled = TRUE; /* Does the server support the SASL-IR capability? */ - else if(wordlen == 7 && !memcmp(line, "SASL-IR", 7)) + else if(wordlen == 7 && curl_strnequal(line, "SASL-IR", 7)) imapc->ir_supported = TRUE; /* Do we have a SASL based authentication mechanism? */ - else if(wordlen > 5 && !memcmp(line, "AUTH=", 5)) { + else if(wordlen > 5 && curl_strnequal(line, "AUTH=", 5)) { size_t llen; unsigned short mechbit; @@ -1196,8 +1187,105 @@ static CURLcode imap_state_listsearch_resp(struct Curl_easy *data, (void)instate; - if(imapcode == '*') - result = Curl_client_write(data, CLIENTWRITE_BODY, line, len); + if(imapcode == '*') { + /* Check if this response contains a literal (e.g. FETCH responses with + body data). Literal syntax is {size}\r\n */ + const char *cr = memchr(line, '\r', len); + size_t line_len = cr ? (size_t)(cr - line) : len; + const char *ptr = memchr(line, '{', line_len); + if(ptr) { + curl_off_t size = 0; + bool parsed = FALSE; + ptr++; + if(!curlx_str_number(&ptr, &size, CURL_OFF_T_MAX) && + !curlx_str_single(&ptr, '}')) + parsed = TRUE; + + if(parsed) { + struct pingpong *pp = &imapc->pp; + size_t buffer_len = curlx_dyn_len(&pp->recvbuf); + size_t after_header = buffer_len - pp->nfinal; + + /* This is a literal response, setup to receive the body data */ + infof(data, "Found %" FMT_OFF_T " bytes to download", size); + + /* First write the header line */ + result = Curl_client_write(data, CLIENTWRITE_BODY, line, len); + if(result) + return result; + + /* Handle data already in buffer after the header line */ + if(after_header > 0) { + /* There is already data in the buffer that is part of the literal + body or subsequent responses */ + size_t chunk = after_header; + + /* Keep only the data after the header line */ + curlx_dyn_tail(&pp->recvbuf, chunk); + pp->nfinal = 0; /* done */ + + /* Limit chunk to the literal size */ + if(chunk > (size_t)size) + chunk = (size_t)size; + + if(chunk) { + /* Write the literal body data */ + result = Curl_client_write(data, CLIENTWRITE_BODY, + curlx_dyn_ptr(&pp->recvbuf), chunk); + if(result) + return result; + } + + /* Handle remaining data in buffer (either more literal data or + subsequent responses) */ + if(after_header > chunk) { + /* Keep the data after the literal body */ + pp->overflow = after_header - chunk; + curlx_dyn_tail(&pp->recvbuf, pp->overflow); + } + else { + pp->overflow = 0; + curlx_dyn_reset(&pp->recvbuf); + } + } + else { + /* No data in buffer yet, reset overflow */ + pp->overflow = 0; + } + + if((CURL_OFF_T_MAX - size) < (curl_off_t)len) + /* unlikely to actually be a transfer this big, but avoid integer + overflow */ + size = CURL_OFF_T_MAX; + else + size += len; + + /* Progress size includes both header line and literal body */ + Curl_pgrsSetDownloadSize(data, size); + + if(data->req.bytecount == size) + /* All data already transferred (header + literal body) */ + Curl_xfer_setup_nop(data); + else { + /* Setup to receive the literal body data. + maxdownload and transfer size include both header line and + literal body */ + data->req.maxdownload = size; + Curl_xfer_setup_recv(data, FIRSTSOCKET, size); + } + /* End of DO phase */ + imap_state(data, imapc, IMAP_STOP); + } + else { + /* Failed to parse literal, just write the line */ + result = Curl_client_write(data, CLIENTWRITE_BODY, line, len); + } + } + else { + /* No literal, just write the line as-is */ + result = Curl_client_write(data, CLIENTWRITE_BODY, line, len); + } + } else if(imapcode != IMAP_RESP_OK) result = CURLE_QUOTE_ERROR; else @@ -1215,38 +1303,32 @@ static CURLcode imap_state_select_resp(struct Curl_easy *data, imapstate instate) { CURLcode result = CURLE_OK; - const char *line = curlx_dyn_ptr(&imapc->pp.recvbuf); - (void)instate; if(imapcode == '*') { /* See if this is an UIDVALIDITY response */ - if(checkprefix("OK [UIDVALIDITY ", line + 2)) { - size_t len = 0; + const char *line = curlx_dyn_ptr(&imapc->pp.recvbuf); + size_t len = curlx_dyn_len(&imapc->pp.recvbuf); + if((len >= 18) && checkprefix("OK [UIDVALIDITY ", &line[2])) { + curl_off_t value; const char *p = &line[2] + strlen("OK [UIDVALIDITY "); - while((len < 20) && p[len] && ISDIGIT(p[len])) - len++; - if(len && (p[len] == ']')) { - struct dynbuf uid; - curlx_dyn_init(&uid, 20); - if(curlx_dyn_addn(&uid, p, len)) - return CURLE_OUT_OF_MEMORY; - free(imapc->mailbox_uidvalidity); - imapc->mailbox_uidvalidity = curlx_dyn_ptr(&uid); + if(!curlx_str_number(&p, &value, UINT_MAX)) { + imapc->mb_uidvalidity = (unsigned int)value; + imapc->mb_uidvalidity_set = TRUE; } } } else if(imapcode == IMAP_RESP_OK) { /* Check if the UIDVALIDITY has been specified and matches */ - if(imap->uidvalidity && imapc->mailbox_uidvalidity && - !curl_strequal(imap->uidvalidity, imapc->mailbox_uidvalidity)) { + if(imap->uidvalidity_set && imapc->mb_uidvalidity_set && + (imap->uidvalidity != imapc->mb_uidvalidity)) { failf(data, "Mailbox UIDVALIDITY has changed"); result = CURLE_REMOTE_FILE_NOT_FOUND; } else { /* Note the currently opened mailbox on this connection */ DEBUGASSERT(!imapc->mailbox); - imapc->mailbox = strdup(imap->mailbox); + imapc->mailbox = curlx_strdup(imap->mailbox); if(!imapc->mailbox) return CURLE_OUT_OF_MEMORY; @@ -1588,9 +1670,6 @@ static CURLcode imap_connect(struct Curl_easy *data, bool *done) if(!imapc) return CURLE_FAILED_INIT; - /* We always support persistent connections in IMAP */ - connkeep(data->conn, "IMAP default"); - /* Parse the URL options */ result = imap_parse_url_options(data->conn, imapc); if(result) @@ -1600,7 +1679,7 @@ static CURLcode imap_connect(struct Curl_easy *data, bool *done) imap_state(data, imapc, IMAP_SERVERGREET); /* Start off with an response id of '*' */ - strcpy(imapc->resptag, "*"); + curlx_strcopy(imapc->resptag, sizeof(imapc->resptag), "*", 1); result = imap_multi_statemach(data, done); @@ -1635,10 +1714,13 @@ static CURLcode imap_done(struct Curl_easy *data, CURLcode status, connclose(conn, "IMAP done with bad status"); /* marked for closure */ result = status; /* use the already set error code */ } - else if(!data->set.connect_only && !imap->custom && - (imap->uid || imap->mindex || data->state.upload || - IS_MIME_POST(data))) { - /* Handle responses after FETCH or APPEND transfer has finished */ + else if(!data->set.connect_only && + ((!imap->custom && (imap->uid || imap->mindex)) || + (imap->custom && data->req.maxdownload > 0) || + data->state.upload || IS_MIME_POST(data))) { + /* Handle responses after FETCH or APPEND transfer has finished. + For custom commands, check if we set up a download which indicates + a FETCH-like command with literal data. */ if(!data->state.upload && !IS_MIME_POST(data)) imap_state(data, imapc, IMAP_FETCH_FINAL); @@ -1690,8 +1772,8 @@ static CURLcode imap_perform(struct Curl_easy *data, bool *connected, has already been selected on this connection */ if(imap->mailbox && imapc->mailbox && curl_strequal(imap->mailbox, imapc->mailbox) && - (!imap->uidvalidity || !imapc->mailbox_uidvalidity || - curl_strequal(imap->uidvalidity, imapc->mailbox_uidvalidity))) + (!imap->uidvalidity_set || !imapc->mb_uidvalidity_set || + (imap->uidvalidity == imapc->mb_uidvalidity))) selected = TRUE; /* Start the first command in the DO phase */ @@ -1708,7 +1790,7 @@ static CURLcode imap_perform(struct Curl_easy *data, bool *connected, /* SEARCH the current mailbox */ result = imap_perform_search(data, imapc, imap); else if(imap->mailbox && !selected && - (imap->custom || imap->uid || imap->mindex || imap->query)) + (imap->custom || imap->uid || imap->mindex || imap->query)) /* SELECT the mailbox */ result = imap_perform_select(data, imapc, imap); else @@ -1843,10 +1925,7 @@ static CURLcode imap_regular_transfer(struct Curl_easy *data, data->req.size = -1; /* Set the progress data */ - Curl_pgrsSetUploadCounter(data, 0); - Curl_pgrsSetDownloadCounter(data, 0); - Curl_pgrsSetUploadSize(data, -1); - Curl_pgrsSetDownloadSize(data, -1); + Curl_pgrsReset(data); /* Carry out the perform */ result = imap_perform(data, &connected, dophase_done); @@ -1861,7 +1940,6 @@ static CURLcode imap_regular_transfer(struct Curl_easy *data, static void imap_easy_reset(struct IMAP *imap) { Curl_safefree(imap->mailbox); - Curl_safefree(imap->uidvalidity); Curl_safefree(imap->uid); Curl_safefree(imap->mindex); Curl_safefree(imap->section); @@ -1879,7 +1957,7 @@ static void imap_easy_dtor(void *key, size_t klen, void *entry) (void)key; (void)klen; imap_easy_reset(imap); - free(imap); + curlx_free(imap); } static void imap_conn_dtor(void *key, size_t klen, void *entry) @@ -1890,8 +1968,7 @@ static void imap_conn_dtor(void *key, size_t klen, void *entry) Curl_pp_disconnect(&imapc->pp); curlx_dyn_free(&imapc->dyn); Curl_safefree(imapc->mailbox); - Curl_safefree(imapc->mailbox_uidvalidity); - free(imapc); + curlx_free(imapc); } static CURLcode imap_setup_connection(struct Curl_easy *data, @@ -1901,7 +1978,7 @@ static CURLcode imap_setup_connection(struct Curl_easy *data, struct pingpong *pp; struct IMAP *imap; - imapc = calloc(1, sizeof(*imapc)); + imapc = curlx_calloc(1, sizeof(*imapc)); if(!imapc) return CURLE_OUT_OF_MEMORY; @@ -1913,12 +1990,12 @@ static CURLcode imap_setup_connection(struct Curl_easy *data, Curl_sasl_init(&imapc->sasl, data, &saslimap); curlx_dyn_init(&imapc->dyn, DYN_IMAP_CMD); - Curl_pp_init(pp); + Curl_pp_init(pp, Curl_pgrs_now(data)); if(Curl_conn_meta_set(conn, CURL_META_IMAP_CONN, imapc, imap_conn_dtor)) return CURLE_OUT_OF_MEMORY; - imap = calloc(1, sizeof(struct IMAP)); + imap = curlx_calloc(1, sizeof(struct IMAP)); if(!imap || Curl_meta_set(data, CURL_META_IMAP_EASY, imap, imap_easy_dtor)) return CURLE_OUT_OF_MEMORY; @@ -1991,7 +2068,7 @@ static char *imap_atom(const char *str, bool escape_only) nclean = strcspn(str, "() {%*]\\\""); if(len == nclean) /* nothing to escape, return a strdup */ - return strdup(str); + return curlx_strdup(str); curlx_dyn_init(&line, 2000); @@ -2028,21 +2105,33 @@ static bool imap_is_bchar(char ch) return TRUE; switch(ch) { - /* bchar */ - case ':': case '@': case '/': - /* bchar -> achar */ - case '&': case '=': - /* bchar -> achar -> uchar -> unreserved (without alphanumeric) */ - case '-': case '.': case '_': case '~': - /* bchar -> achar -> uchar -> sub-delims-sh */ - case '!': case '$': case '\'': case '(': case ')': case '*': - case '+': case ',': - /* bchar -> achar -> uchar -> pct-encoded */ - case '%': /* HEXDIG chars are already included above */ - return TRUE; + /* bchar */ + case ':': + case '@': + case '/': + /* bchar -> achar */ + case '&': + case '=': + /* bchar -> achar -> uchar -> unreserved (without alphanumeric) */ + case '-': + case '.': + case '_': + case '~': + /* bchar -> achar -> uchar -> sub-delims-sh */ + case '!': + case '$': + case '\'': + case '(': + case ')': + case '*': + case '+': + case ',': + /* bchar -> achar -> uchar -> pct-encoded */ + case '%': /* HEXDIG chars are already included above */ + return TRUE; - default: - return FALSE; + default: + return FALSE; } } @@ -2171,68 +2260,61 @@ static CURLcode imap_parse_url_path(struct Curl_easy *data, result = Curl_urldecode(begin, ptr - begin, &value, &valuelen, REJECT_CTRL); if(result) { - free(name); + curlx_free(name); return result; } DEBUGF(infof(data, "IMAP URL parameter '%s' = '%s'", name, value)); - /* Process the known hierarchical parameters (UIDVALIDITY, UID, SECTION and - PARTIAL) stripping of the trailing slash character if it is present. + /* Process the known hierarchical parameters (UIDVALIDITY, UID, SECTION + and PARTIAL) stripping of the trailing slash character if it is + present. Note: Unknown parameters trigger a URL_MALFORMAT error. */ - if(curl_strequal(name, "UIDVALIDITY") && !imap->uidvalidity) { - if(valuelen > 0 && value[valuelen - 1] == '/') - value[valuelen - 1] = '\0'; - - imap->uidvalidity = value; - value = NULL; - } - else if(curl_strequal(name, "UID") && !imap->uid) { - if(valuelen > 0 && value[valuelen - 1] == '/') - value[valuelen - 1] = '\0'; - - imap->uid = value; - value = NULL; - } - else if(curl_strequal(name, "MAILINDEX") && !imap->mindex) { - if(valuelen > 0 && value[valuelen - 1] == '/') - value[valuelen - 1] = '\0'; - - imap->mindex = value; - value = NULL; - } - else if(curl_strequal(name, "SECTION") && !imap->section) { - if(valuelen > 0 && value[valuelen - 1] == '/') - value[valuelen - 1] = '\0'; - - imap->section = value; - value = NULL; - } - else if(curl_strequal(name, "PARTIAL") && !imap->partial) { - if(valuelen > 0 && value[valuelen - 1] == '/') - value[valuelen - 1] = '\0'; - - imap->partial = value; - value = NULL; - } - else { - free(name); - free(value); - - return CURLE_URL_MALFORMAT; + if(valuelen > 0 && value[valuelen - 1] == '/') + value[valuelen - 1] = '\0'; + if(valuelen) { + if(curl_strequal(name, "UIDVALIDITY") && !imap->uidvalidity_set) { + curl_off_t num; + const char *p = (const char *)value; + if(!curlx_str_number(&p, &num, UINT_MAX)) { + imap->uidvalidity = (unsigned int)num; + imap->uidvalidity_set = TRUE; + } + curlx_free(value); + } + else if(curl_strequal(name, "UID") && !imap->uid) { + imap->uid = value; + } + else if(curl_strequal(name, "MAILINDEX") && !imap->mindex) { + imap->mindex = value; + } + else if(curl_strequal(name, "SECTION") && !imap->section) { + imap->section = value; + } + else if(curl_strequal(name, "PARTIAL") && !imap->partial) { + imap->partial = value; + } + else { + curlx_free(name); + curlx_free(value); + return CURLE_URL_MALFORMAT; + } } - - free(name); - free(value); + else + /* blank? */ + curlx_free(value); + curlx_free(name); } /* Does the URL contain a query parameter? Only valid when we have a mailbox and no UID as per RFC-5092 */ if(imap->mailbox && !imap->uid && !imap->mindex) { /* Get the query parameter, URL decoded */ - (void)curl_url_get(data->state.uh, CURLUPART_QUERY, &imap->query, - CURLU_URLDECODE); + CURLUcode uc = curl_url_get(data->state.uh, CURLUPART_QUERY, &imap->query, + CURLU_URLDECODE); + if(uc == CURLUE_OUT_OF_MEMORY) + return CURLE_OUT_OF_MEMORY; } /* Any extra stuff at the end of the URL is an error */ @@ -2266,7 +2348,7 @@ static CURLcode imap_parse_custom_request(struct Curl_easy *data, params++; if(*params) { - imap->custom_params = strdup(params); + imap->custom_params = curlx_strdup(params); imap->custom[params - imap->custom] = '\0'; if(!imap->custom_params) diff --git a/lib/imap.h b/lib/imap.h index f802ed5c0c72..2bab0b4ddea7 100644 --- a/lib/imap.h +++ b/lib/imap.h @@ -27,7 +27,6 @@ #include "pingpong.h" #include "curl_sasl.h" - extern const struct Curl_handler Curl_handler_imap; extern const struct Curl_handler Curl_handler_imaps; @@ -37,6 +36,6 @@ extern const struct Curl_handler Curl_handler_imaps; /* Authentication type values */ #define IMAP_TYPE_NONE 0 -#define IMAP_TYPE_ANY (IMAP_TYPE_CLEARTEXT|IMAP_TYPE_SASL) +#define IMAP_TYPE_ANY (IMAP_TYPE_CLEARTEXT | IMAP_TYPE_SASL) #endif /* HEADER_CURL_IMAP_H */ diff --git a/lib/ldap.c b/lib/ldap.c index 0b475d07bbc4..cad6203eeb35 100644 --- a/lib/ldap.c +++ b/lib/ldap.c @@ -64,46 +64,38 @@ # pragma warning(pop) # endif # include -# ifndef LDAP_VENDOR_NAME -# error Your Platform SDK is NOT sufficient for LDAP support! \ - Update your Platform SDK, or disable LDAP support! -# else -# include -# endif +# include #else # define LDAP_DEPRECATED 1 /* Be sure ldap_init() is defined. */ # ifdef HAVE_LBER_H # include # endif # include -# if (defined(HAVE_LDAP_SSL) && defined(HAVE_LDAP_SSL_H)) +# if defined(HAVE_LDAP_SSL) && defined(HAVE_LDAP_SSL_H) # include # endif /* HAVE_LDAP_SSL && HAVE_LDAP_SSL_H */ #endif #include "urldata.h" -#include #include "cfilters.h" #include "sendf.h" +#include "curl_trc.h" #include "escape.h" #include "progress.h" #include "transfer.h" #include "curlx/strparse.h" +#include "bufref.h" #include "curl_ldap.h" #include "curlx/multibyte.h" #include "curlx/base64.h" #include "connect.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - #ifdef USE_WIN32_LDAP -#define FREE_ON_WINLDAP(x) curlx_unicodefree(x) -#define curl_ldap_num_t ULONG +#define FREE_ON_WINLDAP(x) curlx_free(x) +#define curl_ldap_num_t ULONG #else #define FREE_ON_WINLDAP(x) -#define curl_ldap_num_t int +#define curl_ldap_num_t int #endif #ifndef HAVE_LDAP_URL_PARSE @@ -146,14 +138,15 @@ static void ldap_free_urldesc_low(LDAPURLDesc *ludp); #endif /* !HAVE_LDAP_URL_PARSE */ #ifdef DEBUG_LDAP - #define LDAP_TRACE(x) do { \ - ldap_trace_low("%u: ", __LINE__); \ - ldap_trace_low x; \ - } while(0) +#define LDAP_TRACE(x) \ + do { \ + ldap_trace_low("%u: ", __LINE__); \ + ldap_trace_low x; \ + } while(0) - static void ldap_trace_low(const char *fmt, ...) CURL_PRINTF(1, 2); +static void ldap_trace_low(const char *fmt, ...) CURL_PRINTF(1, 2); #else - #define LDAP_TRACE(x) Curl_nop_stmt +#define LDAP_TRACE(x) Curl_nop_stmt #endif #if defined(USE_WIN32_LDAP) && defined(ldap_err2string) @@ -176,7 +169,6 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done); /* * LDAP protocol handler. */ - const struct Curl_handler Curl_handler_ldap = { "ldap", /* scheme */ ZERO_NULL, /* setup_connection */ @@ -206,7 +198,6 @@ const struct Curl_handler Curl_handler_ldap = { /* * LDAPS protocol handler. */ - const struct Curl_handler Curl_handler_ldaps = { "ldaps", /* scheme */ ZERO_NULL, /* setup_connection */ @@ -300,8 +291,8 @@ static ULONG ldap_win_bind(struct Curl_easy *data, LDAP *server, rc = ldap_simple_bind_s(server, inuser, inpass); - curlx_unicodefree(inuser); - curlx_unicodefree(inpass); + curlx_free(inuser); + curlx_free(inpass); } #ifdef USE_WINDOWS_SSPI else { @@ -343,10 +334,10 @@ 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); - infof(data, "LDAP local: %s", data->state.url); + infof(data, "LDAP local: %s", Curl_bufref_ptr(&data->state.url)); #ifdef HAVE_LDAP_URL_PARSE - rc = ldap_url_parse(data->state.url, &ludp); + rc = ldap_url_parse(Curl_bufref_ptr(&data->state.url), &ludp); #else rc = ldap_url_parse_low(data, conn, &ludp); #endif @@ -382,16 +373,29 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) passwd = conn->passwd; } +#ifdef USE_WIN32_LDAP + if(ldap_ssl) + server = ldap_sslinit(host, (curl_ldap_num_t)ipquad.remote_port, 1); + else +#else + server = ldap_init(host, (curl_ldap_num_t)ipquad.remote_port); +#endif + if(!server) { + failf(data, "LDAP: cannot setup connect to %s:%u", + conn->host.dispname, ipquad.remote_port); + result = CURLE_COULDNT_CONNECT; + goto quit; + } + #ifdef LDAP_OPT_NETWORK_TIMEOUT - ldap_set_option(NULL, LDAP_OPT_NETWORK_TIMEOUT, &ldap_timeout); + ldap_set_option(server, LDAP_OPT_NETWORK_TIMEOUT, &ldap_timeout); #endif - ldap_set_option(NULL, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto); + ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto); if(ldap_ssl) { #ifdef HAVE_LDAP_SSL #ifdef USE_WIN32_LDAP /* Win32 LDAP SDK does not support insecure mode without CA! */ - server = ldap_sslinit(host, (curl_ldap_num_t)ipquad.remote_port, 1); ldap_set_option(server, LDAP_OPT_SSL, LDAP_OPT_ON); #else /* !USE_WIN32_LDAP */ int ldap_option; @@ -399,8 +403,8 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) #ifdef LDAP_OPT_X_TLS if(conn->ssl_config.verifypeer) { /* OpenLDAP SDK supports BASE64 files. */ - if((data->set.ssl.cert_type) && - (!curl_strequal(data->set.ssl.cert_type, "PEM"))) { + if(data->set.ssl.cert_type && + !curl_strequal(data->set.ssl.cert_type, "PEM")) { failf(data, "LDAP local: ERROR OpenLDAP only supports PEM cert-type"); result = CURLE_SSL_CERTPROBLEM; goto quit; @@ -411,7 +415,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) goto quit; } infof(data, "LDAP local: using PEM CA cert: %s", ldap_ca); - rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, ldap_ca); + rc = ldap_set_option(server, LDAP_OPT_X_TLS_CACERTFILE, ldap_ca); if(rc != LDAP_SUCCESS) { failf(data, "LDAP local: ERROR setting PEM CA cert: %s", ldap_err2string(rc)); @@ -423,20 +427,13 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) else ldap_option = LDAP_OPT_X_TLS_NEVER; - rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &ldap_option); + rc = ldap_set_option(server, LDAP_OPT_X_TLS_REQUIRE_CERT, &ldap_option); if(rc != LDAP_SUCCESS) { failf(data, "LDAP local: ERROR setting cert verify mode: %s", ldap_err2string(rc)); result = CURLE_SSL_CERTPROBLEM; goto quit; } - server = ldap_init(host, ipquad.remote_port); - if(!server) { - failf(data, "LDAP local: Cannot connect to %s:%u", - conn->host.dispname, ipquad.remote_port); - result = CURLE_COULDNT_CONNECT; - goto quit; - } ldap_option = LDAP_OPT_X_TLS_HARD; rc = ldap_set_option(server, LDAP_OPT_X_TLS, &ldap_option); if(rc != LDAP_SUCCESS) { @@ -445,23 +442,13 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) result = CURLE_SSL_CERTPROBLEM; goto quit; } -#if 0 - rc = ldap_start_tls_s(server, NULL, NULL); - if(rc != LDAP_SUCCESS) { - failf(data, "LDAP local: ERROR starting SSL/TLS mode: %s", - ldap_err2string(rc)); - result = CURLE_SSL_CERTPROBLEM; - goto quit; - } -#endif - #else /* !LDAP_OPT_X_TLS */ (void)ldap_option; (void)ldap_ca; /* we should probably never come up to here since configure should check in first place if we can support LDAP SSL/TLS */ failf(data, "LDAP local: SSL/TLS not supported with this version " - "of the OpenLDAP toolkit\n"); + "of the OpenLDAP toolkit"); result = CURLE_SSL_CERTPROBLEM; goto quit; #endif /* LDAP_OPT_X_TLS */ @@ -473,15 +460,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) result = CURLE_NOT_BUILT_IN; goto quit; } - else { - server = ldap_init(host, (curl_ldap_num_t)ipquad.remote_port); - if(!server) { - failf(data, "LDAP local: Cannot connect to %s:%u", - conn->host.dispname, ipquad.remote_port); - result = CURLE_COULDNT_CONNECT; - goto quit; - } - } + #ifdef USE_WIN32_LDAP ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto); rc = ldap_win_bind(data, server, user, passwd); @@ -509,7 +488,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) goto quit; } - Curl_pgrsSetDownloadCounter(data, 0); + Curl_pgrsReset(data); rc = ldap_search_s(server, ludp->lud_dn, (curl_ldap_num_t)ludp->lud_scope, ludp->lud_filter, ludp->lud_attrs, 0, &ldapmsg); @@ -623,10 +602,11 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) } if((attr_len > 7) && - (strcmp(";binary", attr + (attr_len - 7)) == 0)) { + curl_strequal(";binary", attr + (attr_len - 7))) { /* Binary attribute, encode to base64. */ if(vals[i]->bv_len) { - result = curlx_base64_encode(vals[i]->bv_val, vals[i]->bv_len, + result = curlx_base64_encode((uint8_t *)vals[i]->bv_val, + vals[i]->bv_len, &val_b64, &val_b64_sz); if(result) { ldap_value_free_len(vals); @@ -641,7 +621,7 @@ static CURLcode ldap_do(struct Curl_easy *data, bool *done) if(val_b64_sz > 0) { result = Curl_client_write(data, CLIENTWRITE_BODY, val_b64, val_b64_sz); - free(val_b64); + curlx_free(val_b64); if(result) { ldap_value_free_len(vals); FREE_ON_WINLDAP(attr); @@ -808,15 +788,15 @@ static curl_ldap_num_t ldap_url_parse2_low(struct Curl_easy *data, ludp->lud_host = conn->host.name; /* Duplicate the path */ - p = path = strdup(data->state.up.path + 1); + p = path = curlx_strdup(data->state.up.path + 1); if(!path) return LDAP_NO_MEMORY; /* Duplicate the query if present */ if(data->state.up.query) { - q = query = strdup(data->state.up.query); + q = query = curlx_strdup(data->state.up.query); if(!query) { - free(path); + curlx_free(path); return LDAP_NO_MEMORY; } } @@ -842,7 +822,7 @@ static curl_ldap_num_t ldap_url_parse2_low(struct Curl_easy *data, ludp->lud_dn = curlx_convert_UTF8_to_tchar(unescaped); /* Free the unescaped string as we are done with it */ - free(unescaped); + curlx_free(unescaped); if(!ludp->lud_dn) { rc = LDAP_NO_MEMORY; @@ -869,9 +849,9 @@ static curl_ldap_num_t ldap_url_parse2_low(struct Curl_easy *data, /* Allocate our array (+1 for the NULL entry) */ #ifdef USE_WIN32_LDAP - ludp->lud_attrs = calloc(count + 1, sizeof(TCHAR *)); + ludp->lud_attrs = curlx_calloc(count + 1, sizeof(TCHAR *)); #else - ludp->lud_attrs = calloc(count + 1, sizeof(char *)); + ludp->lud_attrs = curlx_calloc(count + 1, sizeof(char *)); #endif if(!ludp->lud_attrs) { rc = LDAP_NO_MEMORY; @@ -889,8 +869,7 @@ static curl_ldap_num_t ldap_url_parse2_low(struct Curl_easy *data, LDAP_TRACE(("attr[%zu] '%.*s'\n", i, (int)out.len, out.str)); /* Unescape the attribute */ - result = Curl_urldecode(out.str, out.len, &unescaped, NULL, - REJECT_ZERO); + result = Curl_urldecode(out.str, out.len, &unescaped, NULL, REJECT_ZERO); if(result) { rc = LDAP_NO_MEMORY; goto quit; @@ -901,7 +880,7 @@ static curl_ldap_num_t ldap_url_parse2_low(struct Curl_easy *data, ludp->lud_attrs[i] = curlx_convert_UTF8_to_tchar(unescaped); /* Free the unescaped string as we are done with it */ - free(unescaped); + curlx_free(unescaped); if(!ludp->lud_attrs[i]) { rc = LDAP_NO_MEMORY; @@ -965,7 +944,7 @@ static curl_ldap_num_t ldap_url_parse2_low(struct Curl_easy *data, ludp->lud_filter = curlx_convert_UTF8_to_tchar(unescaped); /* Free the unescaped string as we are done with it */ - free(unescaped); + curlx_free(unescaped); if(!ludp->lud_filter) { rc = LDAP_NO_MEMORY; @@ -985,8 +964,8 @@ static curl_ldap_num_t ldap_url_parse2_low(struct Curl_easy *data, } quit: - free(path); - free(query); + curlx_free(path); + curlx_free(query); return rc; } @@ -995,7 +974,7 @@ static curl_ldap_num_t ldap_url_parse_low(struct Curl_easy *data, const struct connectdata *conn, LDAPURLDesc **ludpp) { - LDAPURLDesc *ludp = calloc(1, sizeof(*ludp)); + LDAPURLDesc *ludp = curlx_calloc(1, sizeof(*ludp)); curl_ldap_num_t rc; *ludpp = NULL; @@ -1016,30 +995,50 @@ static void ldap_free_urldesc_low(LDAPURLDesc *ludp) if(!ludp) return; -#ifdef USE_WIN32_LDAP - curlx_unicodefree(ludp->lud_dn); - curlx_unicodefree(ludp->lud_filter); -#else - free(ludp->lud_dn); - free(ludp->lud_filter); -#endif + curlx_free(ludp->lud_dn); + curlx_free(ludp->lud_filter); if(ludp->lud_attrs) { size_t i; for(i = 0; i < ludp->lud_attrs_dups; i++) { -#ifdef USE_WIN32_LDAP - curlx_unicodefree(ludp->lud_attrs[i]); -#else - free(ludp->lud_attrs[i]); -#endif + curlx_free(ludp->lud_attrs[i]); } - free(ludp->lud_attrs); + curlx_free(ludp->lud_attrs); } - free(ludp); + curlx_free(ludp); } #endif /* !HAVE_LDAP_URL_PARSE */ +void Curl_ldap_version(char *buf, size_t bufsz) +{ +#ifdef USE_WIN32_LDAP + curl_msnprintf(buf, bufsz, "WinLDAP"); +#else +#ifdef LDAP_OPT_X_TLS_PASSPHRASE + static const char *flavor = "/Apple"; +#else + static const char *flavor = ""; +#endif + LDAPAPIInfo api; + api.ldapai_info_version = LDAP_API_INFO_VERSION; + + if(ldap_get_option(NULL, LDAP_OPT_API_INFO, &api) == LDAP_OPT_SUCCESS) { + unsigned int patch = (unsigned int)(api.ldapai_vendor_version % 100); + unsigned int major = (unsigned int)(api.ldapai_vendor_version / 10000); + unsigned int minor = + (((unsigned int)api.ldapai_vendor_version - major * 10000) + - patch) / 100; + curl_msnprintf(buf, bufsz, "%s/%u.%u.%u%s", + api.ldapai_vendor_name, major, minor, patch, flavor); + ldap_memfree(api.ldapai_vendor_name); + ber_memvfree((void **)api.ldapai_extensions); + } + else + curl_msnprintf(buf, bufsz, "LDAP/1"); +#endif +} + #if defined(__GNUC__) && defined(__APPLE__) #pragma GCC diagnostic pop #endif diff --git a/lib/llist.c b/lib/llist.c index c9a7d4a8a789..ce8e064280ea 100644 --- a/lib/llist.c +++ b/lib/llist.c @@ -24,13 +24,7 @@ #include "curl_setup.h" -#include - #include "llist.h" -#include "curl_memory.h" - -/* this must be the last include file */ -#include "memdebug.h" #ifdef DEBUGBUILD #define LLISTINIT 0x100cc001 /* random pattern */ @@ -49,8 +43,7 @@ static struct Curl_llist_node *verifynode(struct Curl_llist_node *n) /* * @unittest: 1300 */ -void -Curl_llist_init(struct Curl_llist *l, Curl_llist_dtor dtor) +void Curl_llist_init(struct Curl_llist *l, Curl_llist_dtor dtor) { l->_size = 0; l->_dtor = dtor; @@ -72,11 +65,10 @@ Curl_llist_init(struct Curl_llist *l, Curl_llist_dtor dtor) * * @unittest: 1300 */ -void -Curl_llist_insert_next(struct Curl_llist *list, - struct Curl_llist_node *e, /* may be NULL */ - const void *p, - struct Curl_llist_node *ne) +void Curl_llist_insert_next(struct Curl_llist *list, + struct Curl_llist_node *e, /* may be NULL */ + const void *p, + struct Curl_llist_node *ne) { DEBUGASSERT(list); DEBUGASSERT(list->_init == LLISTINIT); @@ -123,9 +115,8 @@ Curl_llist_insert_next(struct Curl_llist *list, * * @unittest: 1300 */ -void -Curl_llist_append(struct Curl_llist *list, const void *p, - struct Curl_llist_node *ne) +void Curl_llist_append(struct Curl_llist *list, const void *p, + struct Curl_llist_node *ne) { DEBUGASSERT(list); DEBUGASSERT(list->_init == LLISTINIT); @@ -181,9 +172,8 @@ void *Curl_node_take_elem(struct Curl_llist_node *e) /* * @unittest: 1300 */ -UNITTEST void Curl_node_uremove(struct Curl_llist_node *, void *); -UNITTEST void -Curl_node_uremove(struct Curl_llist_node *e, void *user) +UNITTEST void Curl_node_uremove(struct Curl_llist_node *e, void *user); +UNITTEST void Curl_node_uremove(struct Curl_llist_node *e, void *user) { struct Curl_llist *list; void *ptr; @@ -204,8 +194,7 @@ void Curl_node_remove(struct Curl_llist_node *e) Curl_node_uremove(e, NULL); } -void -Curl_llist_destroy(struct Curl_llist *list, void *user) +void Curl_llist_destroy(struct Curl_llist *list, void *user) { if(list) { DEBUGASSERT(list->_init == LLISTINIT); diff --git a/lib/llist.h b/lib/llist.h index 0a2bc9a62f47..d90dd6846317 100644 --- a/lib/llist.h +++ b/lib/llist.h @@ -25,7 +25,6 @@ ***************************************************************************/ #include "curl_setup.h" -#include typedef void (*Curl_llist_dtor)(void *user, void *elem); @@ -55,8 +54,8 @@ struct Curl_llist_node { void Curl_llist_init(struct Curl_llist *, Curl_llist_dtor); void Curl_llist_insert_next(struct Curl_llist *, struct Curl_llist_node *, const void *, struct Curl_llist_node *node); -void Curl_llist_append(struct Curl_llist *, - const void *, struct Curl_llist_node *node); +void Curl_llist_append(struct Curl_llist *, const void *, + struct Curl_llist_node *node); void Curl_node_remove(struct Curl_llist_node *); void Curl_llist_destroy(struct Curl_llist *, void *); diff --git a/lib/macos.c b/lib/macos.c index daf2ab94f605..8c49a07b8dd0 100644 --- a/lib/macos.c +++ b/lib/macos.c @@ -26,8 +26,6 @@ #ifdef CURL_MACOS_CALL_COPYPROXIES -#include - #include "macos.h" #include diff --git a/lib/md4.c b/lib/md4.c index 9db85786e125..535369579562 100644 --- a/lib/md4.c +++ b/lib/md4.c @@ -26,11 +26,7 @@ #ifdef USE_CURL_NTLM_CORE -#include - -#include "strdup.h" #include "curl_md4.h" -#include "curlx/warnless.h" #ifdef USE_OPENSSL #include @@ -51,14 +47,6 @@ #endif #endif -#ifdef USE_MBEDTLS -#include -#if MBEDTLS_VERSION_NUMBER < 0x03020000 - #error "mbedTLS 3.2.0 or later required" -#endif -#include -#endif /* USE_MBEDTLS */ - /* When OpenSSL or wolfSSL is available, we use their MD4 functions. */ #if defined(USE_WOLFSSL) && !defined(WOLFSSL_NO_MD4) #include @@ -78,22 +66,15 @@ #include #elif defined(USE_GNUTLS) #include -#elif(defined(USE_MBEDTLS) && defined(MBEDTLS_MD4_C)) -#include #endif -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - - #if defined(USE_WOLFSSL) && !defined(WOLFSSL_NO_MD4) #ifdef OPENSSL_COEXIST - #define MD4_CTX WOLFSSL_MD4_CTX - #define MD4_Init wolfSSL_MD4_Init + #define MD4_CTX WOLFSSL_MD4_CTX + #define MD4_Init wolfSSL_MD4_Init #define MD4_Update wolfSSL_MD4_Update - #define MD4_Final wolfSSL_MD4_Final + #define MD4_Final wolfSSL_MD4_Final #endif #elif defined(USE_OPENSSL) && !defined(OPENSSL_NO_MD4) @@ -144,12 +125,7 @@ static int MD4_Init(MD4_CTX *ctx) static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size) { -#ifdef __MINGW32CE__ - CryptHashData(ctx->hHash, (BYTE *)CURL_UNCONST(data), - (unsigned int) size, 0); -#else - CryptHashData(ctx->hHash, (const BYTE *)data, (unsigned int) size, 0); -#endif + CryptHashData(ctx->hHash, (const BYTE *)data, (unsigned int)size, 0); } static void MD4_Final(unsigned char *result, MD4_CTX *ctx) @@ -187,39 +163,6 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx) md4_digest(ctx, MD4_DIGEST_SIZE, result); } -#elif(defined(USE_MBEDTLS) && defined(MBEDTLS_MD4_C)) - -struct md4_ctx { - void *data; - unsigned long size; -}; -typedef struct md4_ctx MD4_CTX; - -static int MD4_Init(MD4_CTX *ctx) -{ - ctx->data = NULL; - ctx->size = 0; - return 1; -} - -static void MD4_Update(MD4_CTX *ctx, const void *data, unsigned long size) -{ - if(!ctx->data) { - ctx->data = Curl_memdup(data, size); - if(ctx->data) - ctx->size = size; - } -} - -static void MD4_Final(unsigned char *result, MD4_CTX *ctx) -{ - if(ctx->data) { - mbedtls_md4(ctx->data, ctx->size, result); - Curl_safefree(ctx->data); - ctx->size = 0; - } -} - #else /* When no other crypto library is available, or the crypto library does not * support MD4, we use this code segment this implementation of it @@ -277,8 +220,8 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx); * The MD4 transformation for all three rounds. */ #define MD4_STEP(f, a, b, c, d, x, s) \ - (a) += f((b), (c), (d)) + (x); \ - (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); + (a) += f((b), (c), (d)) + (x); \ + (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); /* * SET reads 4 input bytes in little-endian byte order and stores them @@ -289,19 +232,15 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx); * does not work. */ #if defined(__i386__) || defined(__x86_64__) || defined(__vax__) -#define MD4_SET(n) \ - (*(const MD4_u32plus *)(const void *)&ptr[(n) * 4]) -#define MD4_GET(n) \ - MD4_SET(n) +#define MD4_SET(n) (*(const MD4_u32plus *)(const void *)&ptr[(n) * 4]) +#define MD4_GET(n) MD4_SET(n) #else -#define MD4_SET(n) \ - (ctx->block[(n)] = \ - (MD4_u32plus)ptr[(n) * 4] | \ - ((MD4_u32plus)ptr[(n) * 4 + 1] << 8) | \ - ((MD4_u32plus)ptr[(n) * 4 + 2] << 16) | \ - ((MD4_u32plus)ptr[(n) * 4 + 3] << 24)) -#define MD4_GET(n) \ - (ctx->block[(n)]) +#define MD4_SET(n) (ctx->block[(n)] = \ + (MD4_u32plus)ptr[(n) * 4] | \ + ((MD4_u32plus)ptr[(n) * 4 + 1] << 8) | \ + ((MD4_u32plus)ptr[(n) * 4 + 2] << 16) | \ + ((MD4_u32plus)ptr[(n) * 4 + 3] << 24)) +#define MD4_GET(n) (ctx->block[(n)]) #endif /* @@ -466,32 +405,32 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx) memset(&ctx->buffer[used], 0, available - 8); ctx->lo <<= 3; - ctx->buffer[56] = curlx_ultouc((ctx->lo)&0xff); - ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8)&0xff); - ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16)&0xff); - ctx->buffer[59] = curlx_ultouc((ctx->lo >> 24)&0xff); - ctx->buffer[60] = curlx_ultouc((ctx->hi)&0xff); - ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8)&0xff); - ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16)&0xff); + ctx->buffer[56] = curlx_ultouc((ctx->lo) & 0xff); + ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8) & 0xff); + ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16) & 0xff); + ctx->buffer[59] = curlx_ultouc((ctx->lo >> 24) & 0xff); + ctx->buffer[60] = curlx_ultouc((ctx->hi) & 0xff); + ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8) & 0xff); + ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16) & 0xff); ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24); my_md4_body(ctx, ctx->buffer, 64); - result[0] = curlx_ultouc((ctx->a)&0xff); - result[1] = curlx_ultouc((ctx->a >> 8)&0xff); - result[2] = curlx_ultouc((ctx->a >> 16)&0xff); + result[0] = curlx_ultouc((ctx->a) & 0xff); + result[1] = curlx_ultouc((ctx->a >> 8) & 0xff); + result[2] = curlx_ultouc((ctx->a >> 16) & 0xff); result[3] = curlx_ultouc(ctx->a >> 24); - result[4] = curlx_ultouc((ctx->b)&0xff); - result[5] = curlx_ultouc((ctx->b >> 8)&0xff); - result[6] = curlx_ultouc((ctx->b >> 16)&0xff); + result[4] = curlx_ultouc((ctx->b) & 0xff); + result[5] = curlx_ultouc((ctx->b >> 8) & 0xff); + result[6] = curlx_ultouc((ctx->b >> 16) & 0xff); result[7] = curlx_ultouc(ctx->b >> 24); - result[8] = curlx_ultouc((ctx->c)&0xff); - result[9] = curlx_ultouc((ctx->c >> 8)&0xff); - result[10] = curlx_ultouc((ctx->c >> 16)&0xff); + result[8] = curlx_ultouc((ctx->c) & 0xff); + result[9] = curlx_ultouc((ctx->c >> 8) & 0xff); + result[10] = curlx_ultouc((ctx->c >> 16) & 0xff); result[11] = curlx_ultouc(ctx->c >> 24); - result[12] = curlx_ultouc((ctx->d)&0xff); - result[13] = curlx_ultouc((ctx->d >> 8)&0xff); - result[14] = curlx_ultouc((ctx->d >> 16)&0xff); + result[12] = curlx_ultouc((ctx->d) & 0xff); + result[13] = curlx_ultouc((ctx->d >> 8) & 0xff); + result[14] = curlx_ultouc((ctx->d >> 16) & 0xff); result[15] = curlx_ultouc(ctx->d >> 24); memset(ctx, 0, sizeof(*ctx)); diff --git a/lib/md5.c b/lib/md5.c index 091924034055..12997d175d76 100644 --- a/lib/md5.c +++ b/lib/md5.c @@ -27,19 +27,8 @@ #if (defined(USE_CURL_NTLM_CORE) && !defined(USE_WINDOWS_SSPI)) || \ !defined(CURL_DISABLE_DIGEST_AUTH) -#include -#include - #include "curl_md5.h" #include "curl_hmac.h" -#include "curlx/warnless.h" - -#ifdef USE_MBEDTLS -#include -#if MBEDTLS_VERSION_NUMBER < 0x03020000 - #error "mbedTLS 3.2.0 or later required" -#endif -#endif /* USE_MBEDTLS */ #ifdef USE_OPENSSL #include @@ -55,14 +44,25 @@ #endif #endif +#ifdef USE_MBEDTLS + #include + #if MBEDTLS_VERSION_NUMBER < 0x03020000 + #error "mbedTLS 3.2.0 or later required" + #endif + #include + #if defined(PSA_WANT_ALG_MD5) && PSA_WANT_ALG_MD5 /* mbedTLS 4+ */ + #define USE_MBEDTLS_MD5 + #endif +#endif + #ifdef USE_GNUTLS #include #elif defined(USE_OPENSSL_MD5) #include #elif defined(USE_WOLFSSL_MD5) #include -#elif defined(USE_MBEDTLS) -#include +#elif defined(USE_MBEDTLS_MD5) +#include #elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \ (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040) && \ defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \ @@ -77,10 +77,6 @@ #include #endif -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - #ifdef USE_GNUTLS typedef struct md5_ctx my_md5_ctx; @@ -152,13 +148,14 @@ static void my_md5_final(unsigned char *digest, void *ctx) (void)wolfSSL_MD5_Final(digest, ctx); } -#elif defined(USE_MBEDTLS) +#elif defined(USE_MBEDTLS_MD5) -typedef mbedtls_md5_context my_md5_ctx; +typedef psa_hash_operation_t my_md5_ctx; static CURLcode my_md5_init(void *ctx) { - if(mbedtls_md5_starts(ctx)) + memset(ctx, 0, sizeof(my_md5_ctx)); + if(psa_hash_setup(ctx, PSA_ALG_MD5) != PSA_SUCCESS) return CURLE_OUT_OF_MEMORY; return CURLE_OK; } @@ -167,12 +164,13 @@ static void my_md5_update(void *ctx, const unsigned char *data, unsigned int length) { - (void)mbedtls_md5_update(ctx, data, length); + (void)psa_hash_update(ctx, data, length); } static void my_md5_final(unsigned char *digest, void *ctx) { - (void)mbedtls_md5_finish(ctx, digest); + size_t actual_length; + (void)psa_hash_finish(ctx, digest, 16, &actual_length); } #elif defined(AN_APPLE_OS) @@ -234,11 +232,7 @@ static void my_md5_update(void *in, unsigned int inputLen) { my_md5_ctx *ctx = in; -#ifdef __MINGW32CE__ - CryptHashData(ctx->hHash, (BYTE *)CURL_UNCONST(input), inputLen, 0); -#else CryptHashData(ctx->hHash, (const BYTE *)input, inputLen, 0); -#endif } static void my_md5_final(unsigned char *digest, void *in) @@ -316,9 +310,9 @@ static void my_md5_final(unsigned char *result, void *ctx); * The MD5 transformation for all four rounds. */ #define MD5_STEP(f, a, b, c, d, x, t, s) \ - (a) += f((b), (c), (d)) + (x) + (t); \ - (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ - (a) += (b); + (a) += f((b), (c), (d)) + (x) + (t); \ + (a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \ + (a) += (b); /* * SET reads 4 input bytes in little-endian byte order and stores them @@ -329,19 +323,15 @@ static void my_md5_final(unsigned char *result, void *ctx); * does not work. */ #if defined(__i386__) || defined(__x86_64__) || defined(__vax__) -#define MD5_SET(n) \ - (*(const MD5_u32plus *)(const void *)&ptr[(n) * 4]) -#define MD5_GET(n) \ - MD5_SET(n) +#define MD5_SET(n) (*(const MD5_u32plus *)(const void *)&ptr[(n) * 4]) +#define MD5_GET(n) MD5_SET(n) #else -#define MD5_SET(n) \ - (ctx->block[(n)] = \ - (MD5_u32plus)ptr[(n) * 4] | \ - ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \ - ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \ - ((MD5_u32plus)ptr[(n) * 4 + 3] << 24)) -#define MD5_GET(n) \ - (ctx->block[(n)]) +#define MD5_SET(n) (ctx->block[(n)] = \ + (MD5_u32plus)ptr[(n) * 4] | \ + ((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \ + ((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \ + ((MD5_u32plus)ptr[(n) * 4 + 3] << 24)) +#define MD5_GET(n) (ctx->block[(n)]) #endif /* @@ -529,32 +519,32 @@ static void my_md5_final(unsigned char *result, void *in) memset(&ctx->buffer[used], 0, available - 8); ctx->lo <<= 3; - ctx->buffer[56] = curlx_ultouc((ctx->lo)&0xff); - ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8)&0xff); - ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16)&0xff); + ctx->buffer[56] = curlx_ultouc((ctx->lo) & 0xff); + ctx->buffer[57] = curlx_ultouc((ctx->lo >> 8) & 0xff); + ctx->buffer[58] = curlx_ultouc((ctx->lo >> 16) & 0xff); ctx->buffer[59] = curlx_ultouc(ctx->lo >> 24); - ctx->buffer[60] = curlx_ultouc((ctx->hi)&0xff); - ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8)&0xff); - ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16)&0xff); + ctx->buffer[60] = curlx_ultouc((ctx->hi) & 0xff); + ctx->buffer[61] = curlx_ultouc((ctx->hi >> 8) & 0xff); + ctx->buffer[62] = curlx_ultouc((ctx->hi >> 16) & 0xff); ctx->buffer[63] = curlx_ultouc(ctx->hi >> 24); my_md5_body(ctx, ctx->buffer, 64); - result[0] = curlx_ultouc((ctx->a)&0xff); - result[1] = curlx_ultouc((ctx->a >> 8)&0xff); - result[2] = curlx_ultouc((ctx->a >> 16)&0xff); + result[0] = curlx_ultouc((ctx->a) & 0xff); + result[1] = curlx_ultouc((ctx->a >> 8) & 0xff); + result[2] = curlx_ultouc((ctx->a >> 16) & 0xff); result[3] = curlx_ultouc(ctx->a >> 24); - result[4] = curlx_ultouc((ctx->b)&0xff); - result[5] = curlx_ultouc((ctx->b >> 8)&0xff); - result[6] = curlx_ultouc((ctx->b >> 16)&0xff); + result[4] = curlx_ultouc((ctx->b) & 0xff); + result[5] = curlx_ultouc((ctx->b >> 8) & 0xff); + result[6] = curlx_ultouc((ctx->b >> 16) & 0xff); result[7] = curlx_ultouc(ctx->b >> 24); - result[8] = curlx_ultouc((ctx->c)&0xff); - result[9] = curlx_ultouc((ctx->c >> 8)&0xff); - result[10] = curlx_ultouc((ctx->c >> 16)&0xff); + result[8] = curlx_ultouc((ctx->c) & 0xff); + result[9] = curlx_ultouc((ctx->c >> 8) & 0xff); + result[10] = curlx_ultouc((ctx->c >> 16) & 0xff); result[11] = curlx_ultouc(ctx->c >> 24); - result[12] = curlx_ultouc((ctx->d)&0xff); - result[13] = curlx_ultouc((ctx->d >> 8)&0xff); - result[14] = curlx_ultouc((ctx->d >> 16)&0xff); + result[12] = curlx_ultouc((ctx->d) & 0xff); + result[13] = curlx_ultouc((ctx->d >> 8) & 0xff); + result[14] = curlx_ultouc((ctx->d >> 16) & 0xff); result[15] = curlx_ultouc(ctx->d >> 24); memset(ctx, 0, sizeof(*ctx)); @@ -602,23 +592,23 @@ struct MD5_context *Curl_MD5_init(const struct MD5_params *md5params) struct MD5_context *ctxt; /* Create MD5 context */ - ctxt = malloc(sizeof(*ctxt)); + ctxt = curlx_malloc(sizeof(*ctxt)); if(!ctxt) return ctxt; - ctxt->md5_hashctx = malloc(md5params->md5_ctxtsize); + ctxt->md5_hashctx = curlx_malloc(md5params->md5_ctxtsize); if(!ctxt->md5_hashctx) { - free(ctxt); + curlx_free(ctxt); return NULL; } ctxt->md5_hash = md5params; if((*md5params->md5_init_func)(ctxt->md5_hashctx)) { - free(ctxt->md5_hashctx); - free(ctxt); + curlx_free(ctxt->md5_hashctx); + curlx_free(ctxt); return NULL; } @@ -638,8 +628,8 @@ CURLcode Curl_MD5_final(struct MD5_context *context, unsigned char *result) { (*context->md5_hash->md5_final_func)(result, context->md5_hashctx); - free(context->md5_hashctx); - free(context); + curlx_free(context->md5_hashctx); + curlx_free(context); return CURLE_OK; } diff --git a/lib/memdebug.c b/lib/memdebug.c index 7ded52c1e97c..b390e81dac0a 100644 --- a/lib/memdebug.c +++ b/lib/memdebug.c @@ -26,14 +26,15 @@ #ifdef CURLDEBUG -#include +#include /* for offsetof() */ #include "urldata.h" -#include "curlx/fopen.h" /* for CURLX_FOPEN_LOW() */ +#include "curl_threads.h" +#include "curlx/fopen.h" /* for CURLX_FOPEN_LOW(), CURLX_FREOPEN_LOW() */ -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" +#ifdef USE_BACKTRACE +#include "backtrace.h" +#endif struct memdebug { size_t size; @@ -51,13 +52,47 @@ struct memdebug { * For advanced analysis, record a log file and write perl scripts to analyze * them! * - * Do not use these with multithreaded test programs! + * Do not use these with multi-threaded test programs! */ FILE *curl_dbg_logfile = NULL; static bool registered_cleanup = FALSE; /* atexit registered cleanup */ static bool memlimit = FALSE; /* enable memory limit */ static long memsize = 0; /* set number of mallocs allowed */ +#ifdef USE_BACKTRACE +static struct backtrace_state *btstate; +#endif + +static char membuf[10000]; +static size_t memwidx = 0; /* write index */ + +#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) +static bool dbg_mutex_init = 0; +static curl_mutex_t dbg_mutex; +#endif + +static bool curl_dbg_lock(void) +{ +#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) + if(dbg_mutex_init) { + Curl_mutex_acquire(&dbg_mutex); + return TRUE; + } +#endif + return FALSE; +} + +static void curl_dbg_unlock(bool was_locked) +{ +#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) + if(was_locked) + Curl_mutex_release(&dbg_mutex); +#else + (void)was_locked; +#endif +} + +static void curl_dbg_log_locked(const char *format, ...) CURL_PRINTF(1, 2); /* LeakSantizier (LSAN) calls _exit() instead of exit() when a leak is detected on exit so the logfile must be closed explicitly or data could be lost. @@ -68,11 +103,47 @@ static void curl_dbg_cleanup(void) if(curl_dbg_logfile && curl_dbg_logfile != stderr && curl_dbg_logfile != stdout) { + if(memwidx) + fwrite(membuf, 1, memwidx, curl_dbg_logfile); /* !checksrc! disable BANNEDFUNC 1 */ fclose(curl_dbg_logfile); } curl_dbg_logfile = NULL; +#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) + if(dbg_mutex_init) { + Curl_mutex_destroy(&dbg_mutex); + dbg_mutex_init = FALSE; + } +#endif } +#ifdef USE_BACKTRACE +static void error_bt_callback(void *data, const char *message, + int error_number) +{ + (void)data; + if(error_number == -1) + curl_dbg_log("compile with -g\n\n"); + else + curl_dbg_log("Backtrace error %d: %s\n", error_number, message); +} + +static int full_callback(void *data, uintptr_t pc, const char *pathname, + int line_number, const char *function) +{ + (void)data; + (void)pc; + if(pathname || function || line_number) + curl_dbg_log("BT %s:%d -- %s\n", pathname, line_number, function); + return 0; +} + +static void dump_bt(void) +{ + backtrace_full(btstate, 0, full_callback, error_bt_callback, NULL); +} +#else +#define dump_bt() /* nothing to do */ +#endif /* this sets the log filename */ void curl_dbg_memdebug(const char *logname) @@ -80,14 +151,21 @@ void curl_dbg_memdebug(const char *logname) if(!curl_dbg_logfile) { if(logname && *logname) curl_dbg_logfile = CURLX_FOPEN_LOW(logname, FOPEN_WRITETEXT); - else - curl_dbg_logfile = stderr; #ifdef MEMDEBUG_LOG_SYNC /* Flush the log file after every line so the log is not lost in a crash */ if(curl_dbg_logfile) setbuf(curl_dbg_logfile, (char *)NULL); #endif } +#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) + if(!dbg_mutex_init) { + dbg_mutex_init = TRUE; + Curl_mutex_init(&dbg_mutex); + } +#endif +#ifdef USE_BACKTRACE + btstate = backtrace_create_state(NULL, 0, error_bt_callback, NULL); +#endif if(!registered_cleanup) registered_cleanup = !atexit(curl_dbg_cleanup); } @@ -110,14 +188,14 @@ static bool countcheck(const char *func, int line, const char *source) if(memlimit && source) { if(!memsize) { /* log to file */ - curl_dbg_log("LIMIT %s:%d %s reached memlimit\n", - source, line, func); + curl_dbg_log("LIMIT %s:%d %s reached memlimit\n", source, line, func); /* log to stderr also */ curl_mfprintf(stderr, "LIMIT %s:%d %s reached memlimit\n", source, line, func); + dump_bt(); fflush(curl_dbg_logfile); /* because it might crash now */ /* !checksrc! disable ERRNOVAR 1 */ - CURL_SETERRNO(ENOMEM); + errno = ENOMEM; return TRUE; /* RETURN ERROR! */ } else @@ -240,6 +318,7 @@ void *curl_dbg_realloc(void *ptr, size_t wantedsize, int line, const char *source) { struct memdebug *mem = NULL; + bool was_locked; size_t size = sizeof(struct memdebug) + wantedsize; @@ -248,6 +327,10 @@ void *curl_dbg_realloc(void *ptr, size_t wantedsize, if(countcheck("realloc", line, source)) return NULL; + /* need to realloc under lock, as we get out-of-order log + * entries otherwise, since another thread might alloc the + * memory released by realloc() before otherwise would log it. */ + was_locked = curl_dbg_lock(); #ifdef __INTEL_COMPILER # pragma warning(push) # pragma warning(disable:1684) @@ -263,10 +346,11 @@ void *curl_dbg_realloc(void *ptr, size_t wantedsize, mem = (Curl_crealloc)(mem, size); if(source) - curl_dbg_log("MEM %s:%d realloc(%p, %zu) = %p\n", - source, line, (void *)ptr, wantedsize, - mem ? (void *)mem->mem : (void *)0); + curl_dbg_log_locked("MEM %s:%d realloc(%p, %zu) = %p\n", + source, line, (void *)ptr, wantedsize, + mem ? (void *)mem->mem : (void *)0); + curl_dbg_unlock(was_locked); if(mem) { mem->size = wantedsize; return mem->mem; @@ -280,6 +364,9 @@ void curl_dbg_free(void *ptr, int line, const char *source) if(ptr) { struct memdebug *mem; + if(source) + curl_dbg_log("MEM %s:%d free(%p)\n", source, line, (void *)ptr); + #ifdef __INTEL_COMPILER # pragma warning(push) # pragma warning(disable:1684) @@ -295,9 +382,6 @@ void curl_dbg_free(void *ptr, int line, const char *source) /* free for real */ (Curl_cfree)(mem); } - - if(source && ptr) - curl_dbg_log("MEM %s:%d free(%p)\n", source, line, (void *)ptr); } curl_socket_t curl_dbg_socket(int domain, int type, int protocol, @@ -330,7 +414,7 @@ SEND_TYPE_RETV curl_dbg_send(SEND_TYPE_ARG1 sockfd, rc = send(sockfd, buf, len, flags); if(source) curl_dbg_log("SEND %s:%d send(%lu) = %ld\n", - source, line, (unsigned long)len, (long)rc); + source, line, (unsigned long)len, (long)rc); return rc; } @@ -345,7 +429,7 @@ RECV_TYPE_RETV curl_dbg_recv(RECV_TYPE_ARG1 sockfd, RECV_TYPE_ARG2 buf, rc = recv(sockfd, buf, len, flags); if(source) curl_dbg_log("RECV %s:%d recv(%lu) = %ld\n", - source, line, (unsigned long)len, (long)rc); + source, line, (unsigned long)len, (long)rc); return rc; } @@ -412,9 +496,8 @@ void curl_dbg_mark_sclose(curl_socket_t sockfd, int line, const char *source) /* this is our own defined way to close sockets on *ALL* platforms */ int curl_dbg_sclose(curl_socket_t sockfd, int line, const char *source) { - int res = CURL_SCLOSE(sockfd); curl_dbg_mark_sclose(sockfd, line, source); - return res; + return CURL_SCLOSE(sockfd); } ALLOC_FUNC @@ -424,7 +507,19 @@ FILE *curl_dbg_fopen(const char *file, const char *mode, FILE *res = CURLX_FOPEN_LOW(file, mode); if(source) curl_dbg_log("FILE %s:%d fopen(\"%s\",\"%s\") = %p\n", - source, line, file, mode, (void *)res); + source, line, file, mode, (void *)res); + + return res; +} + +ALLOC_FUNC +FILE *curl_dbg_freopen(const char *file, const char *mode, FILE *fh, + int line, const char *source) +{ + FILE *res = CURLX_FREOPEN_LOW(file, mode, fh); + if(source) + curl_dbg_log("FILE %s:%d freopen(\"%s\",\"%s\",%p) = %p\n", + source, line, file, mode, (void *)fh, (void *)res); return res; } @@ -448,8 +543,7 @@ int curl_dbg_fclose(FILE *file, int line, const char *source) DEBUGASSERT(file != NULL); if(source) - curl_dbg_log("FILE %s:%d fclose(%p)\n", - source, line, (void *)file); + curl_dbg_log("FILE %s:%d fclose(%p)\n", source, line, (void *)file); /* !checksrc! disable BANNEDFUNC 1 */ res = fclose(file); @@ -457,25 +551,59 @@ int curl_dbg_fclose(FILE *file, int line, const char *source) return res; } -/* this does the writing to the memory tracking log file */ -void curl_dbg_log(const char *format, ...) +static void curl_dbg_vlog(const char * const fmt, + va_list ap) CURL_PRINTF(1, 0); + +static void curl_dbg_vlog(const char * const fmt, va_list ap) { char buf[1024]; - int nchars; + size_t nchars = curl_mvsnprintf(buf, sizeof(buf), fmt, ap); + + if(nchars > (int)sizeof(buf) - 1) + nchars = (int)sizeof(buf) - 1; + + if(nchars > 0) { + if(sizeof(membuf) - nchars < memwidx) { + /* flush */ + fwrite(membuf, 1, memwidx, curl_dbg_logfile); + fflush(curl_dbg_logfile); + memwidx = 0; + } + if(memwidx) { + /* the previous line ends with a newline */ + DEBUGASSERT(membuf[memwidx - 1] == '\n'); + } + memcpy(&membuf[memwidx], buf, nchars); + memwidx += nchars; + } +} + +static void curl_dbg_log_locked(const char *format, ...) +{ va_list ap; if(!curl_dbg_logfile) return; va_start(ap, format); - nchars = curl_mvsnprintf(buf, sizeof(buf), format, ap); + curl_dbg_vlog(format, ap); va_end(ap); +} - if(nchars > (int)sizeof(buf) - 1) - nchars = (int)sizeof(buf) - 1; +/* this does the writing to the memory tracking log file */ +void curl_dbg_log(const char *format, ...) +{ + bool was_locked; + va_list ap; + + if(!curl_dbg_logfile) + return; - if(nchars > 0) - (fwrite)(buf, 1, (size_t)nchars, curl_dbg_logfile); + was_locked = curl_dbg_lock(); + va_start(ap, format); + curl_dbg_vlog(format, ap); + va_end(ap); + curl_dbg_unlock(was_locked); } #endif /* CURLDEBUG */ diff --git a/lib/mime.c b/lib/mime.c index b403d29b1fd9..011201a7cb82 100644 --- a/lib/mime.c +++ b/lib/mime.c @@ -24,16 +24,15 @@ #include "curl_setup.h" -#include - struct Curl_easy; #include "mime.h" -#include "curlx/warnless.h" #include "urldata.h" #include "sendf.h" +#include "curl_trc.h" #include "transfer.h" #include "strdup.h" +#include "curlx/strcopy.h" #include "curlx/fopen.h" #include "curlx/base64.h" @@ -50,18 +49,14 @@ struct Curl_easy; #include "slist.h" #include "curlx/dynbuf.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - #ifdef _WIN32 # ifndef R_OK # define R_OK 4 # endif #endif -#define READ_ERROR ((size_t) -1) -#define STOP_FILLING ((size_t) -2) +#define READ_ERROR ((size_t)-1) +#define STOP_FILLING ((size_t)-2) static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems, void *instream, bool *hasread); @@ -81,12 +76,12 @@ static curl_off_t encoder_qp_size(curl_mimepart *part); static curl_off_t mime_size(curl_mimepart *part); static const struct mime_encoder encoders[] = { - {"binary", encoder_nop_read, encoder_nop_size}, - {"8bit", encoder_nop_read, encoder_nop_size}, - {"7bit", encoder_7bit_read, encoder_nop_size}, - {"base64", encoder_base64_read, encoder_base64_size}, - {"quoted-printable", encoder_qp_read, encoder_qp_size}, - {ZERO_NULL, ZERO_NULL, ZERO_NULL} + { "binary", encoder_nop_read, encoder_nop_size }, + { "8bit", encoder_nop_read, encoder_nop_size }, + { "7bit", encoder_7bit_read, encoder_nop_size }, + { "base64", encoder_base64_read, encoder_base64_size }, + { "quoted-printable", encoder_qp_read, encoder_qp_size }, + { ZERO_NULL, ZERO_NULL, ZERO_NULL } }; /* Quoted-printable character class table. @@ -124,15 +119,13 @@ static const unsigned char qp_class[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* F0 - FF */ }; - /* Binary --> hexadecimal ASCII table. */ static const char aschex[] = "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x41\x42\x43\x44\x45\x46"; - #ifndef __VMS #define filesize(name, stat_data) (stat_data.st_size) -#define fopen_read curlx_fopen +#define fopen_read curlx_fopen #else @@ -147,13 +140,12 @@ static const char aschex[] = * and CD/DVD images should be either a STREAM_LF format or a fixed format. * */ -curl_off_t VmsRealFileSize(const char *name, - const struct_stat *stat_buf) +curl_off_t VmsRealFileSize(const char *name, const struct_stat *stat_buf) { char buffer[8192]; curl_off_t count; int ret_stat; - FILE * file; + FILE *file; file = curlx_fopen(name, FOPEN_READTEXT); /* VMS */ if(!file) @@ -177,8 +169,7 @@ curl_off_t VmsRealFileSize(const char *name, * if not to call a routine to get the correct size. * */ -static curl_off_t VmsSpecialSize(const char *name, - const struct_stat *stat_buf) +static curl_off_t VmsSpecialSize(const char *name, const struct_stat *stat_buf) { switch(stat_buf->st_fab_rfm) { case FAB$C_VAR: @@ -200,7 +191,7 @@ static curl_off_t VmsSpecialSize(const char *name, * record format of the file. * */ -static FILE * vmsfopenread(const char *file, const char *mode) +static FILE *vmsfopenread(const char *file, const char *mode) { struct_stat statbuf; int result; @@ -221,7 +212,6 @@ static FILE * vmsfopenread(const char *file, const char *mode) #define fopen_read vmsfopenread #endif - #ifndef HAVE_BASENAME /* (Quote from The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004 @@ -268,10 +258,9 @@ static char *Curl_basename(char *path) return path; } -#define basename(x) Curl_basename((x)) +#define basename(x) Curl_basename(x) #endif - /* Set readback state. */ static void mimesetstate(struct mime_state *state, enum mimestate tok, void *ptr) @@ -281,7 +270,6 @@ static void mimesetstate(struct mime_state *state, state->offset = 0; } - /* Escape header string into allocated memory. */ static char *escape_string(struct Curl_easy *data, const char *src, enum mimestrategy strategy) @@ -357,13 +345,13 @@ static char *strippath(const char *fullfile) { char *filename; char *base; - filename = strdup(fullfile); /* duplicate since basename() may ruin the - buffer it works on */ + filename = curlx_strdup(fullfile); /* duplicate since basename() may ruin + the buffer it works on */ if(!filename) return NULL; - base = strdup(basename(filename)); + base = curlx_strdup(basename(filename)); - free(filename); /* free temporary buffer */ + curlx_free(filename); /* free temporary buffer */ return base; /* returns an allocated string or NULL ! */ } @@ -376,7 +364,6 @@ static void cleanup_encoder_state(struct mime_encoder_state *p) p->bufend = 0; } - /* Dummy encoder. This is used for 8bit and binary content encodings. */ static size_t encoder_nop_read(char *buffer, size_t size, bool ateof, struct curl_mimepart *part) @@ -404,7 +391,6 @@ static curl_off_t encoder_nop_size(curl_mimepart *part) return part->datasize; } - /* 7bit encoder: the encoder is just a data validity check. */ static size_t encoder_7bit_read(char *buffer, size_t size, bool ateof, curl_mimepart *part) @@ -430,7 +416,6 @@ static size_t encoder_7bit_read(char *buffer, size_t size, bool ateof, return cursize; } - /* Base64 content encoder. */ static size_t encoder_base64_read(char *buffer, size_t size, bool ateof, curl_mimepart *part) @@ -469,10 +454,10 @@ static size_t encoder_base64_read(char *buffer, size_t size, bool ateof, i = st->buf[st->bufbeg++] & 0xFF; i = (i << 8) | (st->buf[st->bufbeg++] & 0xFF); i = (i << 8) | (st->buf[st->bufbeg++] & 0xFF); - *ptr++ = Curl_base64encdec[(i >> 18) & 0x3F]; - *ptr++ = Curl_base64encdec[(i >> 12) & 0x3F]; - *ptr++ = Curl_base64encdec[(i >> 6) & 0x3F]; - *ptr++ = Curl_base64encdec[i & 0x3F]; + *ptr++ = curlx_base64encdec[(i >> 18) & 0x3F]; + *ptr++ = curlx_base64encdec[(i >> 12) & 0x3F]; + *ptr++ = curlx_base64encdec[(i >> 6) & 0x3F]; + *ptr++ = curlx_base64encdec[i & 0x3F]; cursize += 4; st->pos += 4; size -= 4; @@ -496,10 +481,10 @@ static size_t encoder_base64_read(char *buffer, size_t size, bool ateof, i = (st->buf[st->bufbeg + 1] & 0xFF) << 8; i |= (st->buf[st->bufbeg] & 0xFF) << 16; - ptr[0] = Curl_base64encdec[(i >> 18) & 0x3F]; - ptr[1] = Curl_base64encdec[(i >> 12) & 0x3F]; + ptr[0] = curlx_base64encdec[(i >> 18) & 0x3F]; + ptr[1] = curlx_base64encdec[(i >> 12) & 0x3F]; if(++st->bufbeg != st->bufend) { - ptr[2] = Curl_base64encdec[(i >> 6) & 0x3F]; + ptr[2] = curlx_base64encdec[(i >> 6) & 0x3F]; st->bufbeg++; } cursize += 4; @@ -525,7 +510,6 @@ static curl_off_t encoder_base64_size(curl_mimepart *part) return size + 2 * ((size - 1) / MAX_ENCODED_LINE_LENGTH); } - /* Quoted-printable lookahead. * * Check if a CRLF or end of data is in input buffer at current position + n. @@ -562,7 +546,7 @@ static size_t encoder_qp_read(char *buffer, size_t size, bool ateof, size_t len = 1; size_t consumed = 1; int i = st->buf[st->bufbeg]; - buf[0] = (char) i; + buf[0] = (char)i; buf[1] = aschex[(i >> 4) & 0xF]; buf[2] = aschex[i & 0xF]; @@ -619,7 +603,7 @@ static size_t encoder_qp_read(char *buffer, size_t size, bool ateof, } } if(softlinebreak) { - strcpy(buf, "\x3D\x0D\x0A"); /* "=\r\n" */ + curlx_strcopy(buf, sizeof(buf), "\x3D\x0D\x0A", 3); /* "=\r\n" */ len = 3; consumed = 0; } @@ -653,13 +637,12 @@ static curl_off_t encoder_qp_size(curl_mimepart *part) return part->datasize ? -1 : 0; } - /* In-memory data callbacks. */ /* Argument is a pointer to the mime part. */ static size_t mime_mem_read(char *buffer, size_t size, size_t nitems, void *instream) { - curl_mimepart *part = (curl_mimepart *) instream; + curl_mimepart *part = (curl_mimepart *)instream; size_t sz = curlx_sotouz(part->datasize - part->state.offset); (void)size; /* Always 1 */ @@ -677,7 +660,7 @@ static size_t mime_mem_read(char *buffer, size_t size, size_t nitems, static int mime_mem_seek(void *instream, curl_off_t offset, int whence) { - curl_mimepart *part = (curl_mimepart *) instream; + curl_mimepart *part = (curl_mimepart *)instream; switch(whence) { case SEEK_CUR: @@ -697,26 +680,25 @@ static int mime_mem_seek(void *instream, curl_off_t offset, int whence) static void mime_mem_free(void *ptr) { - Curl_safefree(((curl_mimepart *) ptr)->data); + Curl_safefree(((curl_mimepart *)ptr)->data); } - /* Named file callbacks. */ /* Argument is a pointer to the mime part. */ -static int mime_open_file(curl_mimepart *part) +static bool mime_open_file(curl_mimepart *part) { /* Open a MIMEKIND_FILE part. */ if(part->fp) - return 0; + return FALSE; part->fp = fopen_read(part->data, "rb"); - return part->fp ? 0 : -1; + return part->fp ? FALSE : TRUE; } static size_t mime_file_read(char *buffer, size_t size, size_t nitems, void *instream) { - curl_mimepart *part = (curl_mimepart *) instream; + curl_mimepart *part = (curl_mimepart *)instream; if(!nitems) return STOP_FILLING; @@ -729,7 +711,7 @@ static size_t mime_file_read(char *buffer, size_t size, size_t nitems, static int mime_file_seek(void *instream, curl_off_t offset, int whence) { - curl_mimepart *part = (curl_mimepart *) instream; + curl_mimepart *part = (curl_mimepart *)instream; if(whence == SEEK_SET && !offset && !part->fp) return CURL_SEEKFUNC_OK; /* Not open: implicitly already at BOF. */ @@ -737,13 +719,13 @@ static int mime_file_seek(void *instream, curl_off_t offset, int whence) if(mime_open_file(part)) return CURL_SEEKFUNC_FAIL; - return fseek(part->fp, (long) offset, whence) ? + return curlx_fseek(part->fp, offset, whence) ? CURL_SEEKFUNC_CANTSEEK : CURL_SEEKFUNC_OK; } static void mime_file_free(void *ptr) { - curl_mimepart *part = (curl_mimepart *) ptr; + curl_mimepart *part = (curl_mimepart *)ptr; if(part->fp) { curlx_fclose(part->fp); @@ -752,7 +734,6 @@ static void mime_file_free(void *ptr) Curl_safefree(part->data); } - /* Subparts callbacks. */ /* Argument is a pointer to the mime structure. */ @@ -802,7 +783,7 @@ static size_t read_part_content(curl_mimepart *part, } /* If we can determine we are at end of part data, spare a read. */ - if(part->datasize != (curl_off_t) -1 && + if(part->datasize != (curl_off_t)-1 && part->state.offset >= part->datasize) { /* sz is already zero. */ } @@ -813,8 +794,8 @@ static size_t read_part_content(curl_mimepart *part, * Cannot be processed as other kinds since read function requires * an additional parameter and is highly recursive. */ - sz = mime_subparts_read(buffer, 1, bufsize, part->arg, hasread); - break; + sz = mime_subparts_read(buffer, 1, bufsize, part->arg, hasread); + break; case MIMEKIND_FILE: if(part->fp && feof(part->fp)) break; /* At EOF. */ @@ -920,7 +901,7 @@ static size_t readback_part(curl_mimepart *part, while(bufsize) { size_t sz = 0; - struct curl_slist *hdr = (struct curl_slist *) part->state.ptr; + struct curl_slist *hdr = (struct curl_slist *)part->state.ptr; switch(part->state.state) { case MIMESTATE_BEGIN: mimesetstate(&part->state, @@ -998,7 +979,7 @@ static size_t readback_part(curl_mimepart *part, static size_t mime_subparts_read(char *buffer, size_t size, size_t nitems, void *instream, bool *hasread) { - curl_mime *mime = (curl_mime *) instream; + curl_mime *mime = (curl_mime *)instream; size_t cursize = 0; (void)size; /* Always 1 */ @@ -1074,7 +1055,7 @@ static int mime_part_rewind(curl_mimepart *part) if(part->state.state > targetstate) { res = CURL_SEEKFUNC_CANTSEEK; if(part->seekfunc) { - res = part->seekfunc(part->arg, (curl_off_t) 0, SEEK_SET); + res = part->seekfunc(part->arg, (curl_off_t)0, SEEK_SET); switch(res) { case CURL_SEEKFUNC_OK: case CURL_SEEKFUNC_FAIL: @@ -1099,7 +1080,7 @@ static int mime_part_rewind(curl_mimepart *part) static int mime_subparts_seek(void *instream, curl_off_t offset, int whence) { - curl_mime *mime = (curl_mime *) instream; + curl_mime *mime = (curl_mime *)instream; curl_mimepart *part; int result = CURL_SEEKFUNC_OK; @@ -1130,10 +1111,10 @@ static void cleanup_part_content(curl_mimepart *part) part->readfunc = NULL; part->seekfunc = NULL; part->freefunc = NULL; - part->arg = (void *) part; /* Defaults to part itself. */ + part->arg = (void *)part; /* Defaults to part itself. */ part->data = NULL; part->fp = NULL; - part->datasize = (curl_off_t) 0; /* No size yet. */ + part->datasize = (curl_off_t)0; /* No size yet. */ cleanup_encoder_state(&part->encstate); part->kind = MIMEKIND_NONE; part->flags &= ~(unsigned int)MIME_FAST_READ; @@ -1143,7 +1124,7 @@ static void cleanup_part_content(curl_mimepart *part) static void mime_subparts_free(void *ptr) { - curl_mime *mime = (curl_mime *) ptr; + curl_mime *mime = (curl_mime *)ptr; if(mime && mime->parent) { mime->parent->freefunc = NULL; /* Be sure we will not be called again. */ @@ -1155,7 +1136,7 @@ static void mime_subparts_free(void *ptr) /* Do not free subparts: unbind them. This is used for the top level only. */ static void mime_subparts_unbind(void *ptr) { - curl_mime *mime = (curl_mime *) ptr; + curl_mime *mime = (curl_mime *)ptr; if(mime && mime->parent) { mime->parent->freefunc = NULL; /* Be sure we will not be called again. */ @@ -1164,7 +1145,6 @@ static void mime_subparts_unbind(void *ptr) } } - void Curl_mime_cleanpart(curl_mimepart *part) { if(part) { @@ -1190,9 +1170,9 @@ void curl_mime_free(curl_mime *mime) part = mime->firstpart; mime->firstpart = part->nextpart; Curl_mime_cleanpart(part); - free(part); + curlx_free(part); } - free(mime); + curlx_free(mime); } } @@ -1211,7 +1191,7 @@ CURLcode Curl_mime_duppart(struct Curl_easy *data, case MIMEKIND_NONE: break; case MIMEKIND_DATA: - res = curl_mime_data(dst, src->data, (size_t) src->datasize); + res = curl_mime_data(dst, src->data, (size_t)src->datasize); break; case MIMEKIND_FILE: res = curl_mime_filedata(dst, src->data); @@ -1230,7 +1210,7 @@ CURLcode Curl_mime_duppart(struct Curl_easy *data, res = mime ? curl_mime_subparts(dst, mime) : CURLE_OUT_OF_MEMORY; /* Duplicate subparts. */ - for(s = ((curl_mime *) src->arg)->firstpart; !res && s; s = s->nextpart) { + for(s = ((curl_mime *)src->arg)->firstpart; !res && s; s = s->nextpart) { d = curl_mime_addpart(mime); res = d ? Curl_mime_duppart(data, d, s) : CURLE_OUT_OF_MEMORY; } @@ -1282,7 +1262,7 @@ curl_mime *curl_mime_init(void *easy) { curl_mime *mime; - mime = (curl_mime *) malloc(sizeof(*mime)); + mime = (curl_mime *)curlx_malloc(sizeof(*mime)); if(mime) { mime->parent = NULL; @@ -1291,10 +1271,10 @@ curl_mime *curl_mime_init(void *easy) memset(mime->boundary, '-', MIME_BOUNDARY_DASHES); if(Curl_rand_alnum(easy, - (unsigned char *) &mime->boundary[MIME_BOUNDARY_DASHES], + (unsigned char *)&mime->boundary[MIME_BOUNDARY_DASHES], MIME_RAND_BOUNDARY_CHARS + 1)) { /* failed to get random separator, bail out */ - free(mime); + curlx_free(mime); return NULL; } mimesetstate(&mime->state, MIMESTATE_BEGIN, NULL); @@ -1306,7 +1286,7 @@ curl_mime *curl_mime_init(void *easy) /* Initialize a mime part. */ void Curl_mime_initpart(curl_mimepart *part) { - memset((char *) part, 0, sizeof(*part)); + memset((char *)part, 0, sizeof(*part)); part->lastreadstatus = 1; /* Successful read status. */ mimesetstate(&part->state, MIMESTATE_BEGIN, NULL); } @@ -1319,7 +1299,7 @@ curl_mimepart *curl_mime_addpart(curl_mime *mime) if(!mime) return NULL; - part = (curl_mimepart *) malloc(sizeof(*part)); + part = (curl_mimepart *)curlx_malloc(sizeof(*part)); if(part) { Curl_mime_initpart(part); @@ -1345,7 +1325,7 @@ CURLcode curl_mime_name(curl_mimepart *part, const char *name) Curl_safefree(part->name); if(name) { - part->name = strdup(name); + part->name = curlx_strdup(name); if(!part->name) return CURLE_OUT_OF_MEMORY; } @@ -1362,7 +1342,7 @@ CURLcode curl_mime_filename(curl_mimepart *part, const char *filename) Curl_safefree(part->filename); if(filename) { - part->filename = strdup(filename); + part->filename = curlx_strdup(filename); if(!part->filename) return CURLE_OUT_OF_MEMORY; } @@ -1371,8 +1351,7 @@ 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 *ptr, size_t datasize) +CURLcode curl_mime_data(curl_mimepart *part, const char *ptr, size_t datasize) { if(!part) return CURLE_BAD_FUNCTION_ARGUMENT; @@ -1415,7 +1394,7 @@ CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename) if(curlx_stat(filename, &sbuf)) result = CURLE_READ_ERROR; else { - part->data = strdup(filename); + part->data = curlx_strdup(filename); if(!part->data) result = CURLE_OUT_OF_MEMORY; else { @@ -1438,7 +1417,7 @@ CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename) result = CURLE_OUT_OF_MEMORY; else { result = curl_mime_filename(part, base); - free(base); + curlx_free(base); } } } @@ -1455,7 +1434,7 @@ CURLcode curl_mime_type(curl_mimepart *part, const char *mimetype) Curl_safefree(part->mimetype); if(mimetype) { - part->mimetype = strdup(mimetype); + part->mimetype = curlx_strdup(mimetype); if(!part->mimetype) return CURLE_OUT_OF_MEMORY; } @@ -1562,7 +1541,7 @@ CURLcode Curl_mime_set_subparts(curl_mimepart *part, they might not be positioned at start. Rewind them now, as a future check while rewinding the parent may cause this content to be skipped. */ - if(mime_subparts_seek(subparts, (curl_off_t) 0, SEEK_SET) != + if(mime_subparts_seek(subparts, (curl_off_t)0, SEEK_SET) != CURL_SEEKFUNC_OK) return CURLE_SEND_FAIL_REWIND; @@ -1584,12 +1563,11 @@ CURLcode curl_mime_subparts(curl_mimepart *part, curl_mime *subparts) return Curl_mime_set_subparts(part, subparts, TRUE); } - /* Readback from top mime. */ /* Argument is the dummy top part. */ size_t Curl_mime_read(char *buffer, size_t size, size_t nitems, void *instream) { - curl_mimepart *part = (curl_mimepart *) instream; + curl_mimepart *part = (curl_mimepart *)instream; size_t ret; bool hasread; @@ -1672,8 +1650,7 @@ static curl_off_t mime_size(curl_mimepart *part) if(size >= 0 && !(part->flags & MIME_BODY_ONLY)) { /* Compute total part size. */ size += slist_size(part->curlheaders, 2, NULL, 0); - size += slist_size(part->userheaders, 2, - STRCONST("Content-Type")); + size += slist_size(part->userheaders, 2, STRCONST("Content-Type")); size += 2; /* CRLF after headers. */ } return size; @@ -1696,7 +1673,7 @@ CURLcode Curl_mime_add_header(struct curl_slist **slp, const char *fmt, ...) if(hdr) *slp = hdr; else - free(s); + curlx_free(s); } return hdr ? CURLE_OK : CURLE_OUT_OF_MEMORY; @@ -1722,16 +1699,16 @@ const char *Curl_mime_contenttype(const char *filename) const char *type; }; static const struct ContentType ctts[] = { - {".gif", "image/gif"}, - {".jpg", "image/jpeg"}, - {".jpeg", "image/jpeg"}, - {".png", "image/png"}, - {".svg", "image/svg+xml"}, - {".txt", "text/plain"}, - {".htm", "text/html"}, - {".html", "text/html"}, - {".pdf", "application/pdf"}, - {".xml", "application/xml"} + { ".gif", "image/gif" }, + { ".jpg", "image/jpeg" }, + { ".jpeg", "image/jpeg" }, + { ".png", "image/png" }, + { ".svg", "image/svg+xml" }, + { ".txt", "text/plain" }, + { ".htm", "text/html" }, + { ".html", "text/html" }, + { ".pdf", "application/pdf" }, + { ".xml", "application/xml" } }; if(filename) { @@ -1812,7 +1789,7 @@ CURLcode Curl_mime_prepare_headers(struct Curl_easy *data, } if(part->kind == MIMEKIND_MULTIPART) { - mime = (curl_mime *) part->arg; + mime = (curl_mime *)part->arg; if(mime) boundary = mime->boundary; } @@ -1825,10 +1802,10 @@ CURLcode Curl_mime_prepare_headers(struct Curl_easy *data, if(!search_header(part->userheaders, STRCONST("Content-Disposition"))) { if(!disposition) if(part->filename || part->name || - (contenttype && !curl_strnequal(contenttype, "multipart/", 10))) - disposition = DISPOSITION_DEFAULT; + (contenttype && !curl_strnequal(contenttype, "multipart/", 10))) + disposition = DISPOSITION_DEFAULT; if(disposition && curl_strequal(disposition, "attachment") && - !part->name && !part->filename) + !part->name && !part->filename) disposition = NULL; if(disposition) { char *name = NULL; @@ -1858,8 +1835,8 @@ CURLcode Curl_mime_prepare_headers(struct Curl_easy *data, Curl_safefree(filename); if(ret) return ret; - } } + } /* Issue Content-Type header. */ if(contenttype) { @@ -1874,7 +1851,7 @@ CURLcode Curl_mime_prepare_headers(struct Curl_easy *data, if(part->encoder) cte = part->encoder->name; else if(contenttype && strategy == MIMESTRATEGY_MAIL && - part->kind != MIMEKIND_MULTIPART) + part->kind != MIMEKIND_MULTIPART) cte = "8bit"; if(cte) { ret = Curl_mime_add_header(&part->curlheaders, @@ -1913,7 +1890,7 @@ static void mime_unpause(curl_mimepart *part) if(part->lastreadstatus == CURL_READFUNC_PAUSE) part->lastreadstatus = 1; /* Successful read status. */ if(part->kind == MIMEKIND_MULTIPART) { - curl_mime *mime = (curl_mime *) part->arg; + curl_mime *mime = (curl_mime *)part->arg; if(mime) { curl_mimepart *subpart; @@ -1966,7 +1943,6 @@ static CURLcode cr_mime_read(struct Curl_easy *data, size_t nread; char tmp[256]; - /* Once we have errored, we will return the same error forever */ if(ctx->errored) { CURL_TRC_READ(data, "cr_mime_read(len=%zu) is errored -> %d, eos=0", @@ -2118,7 +2094,7 @@ static CURLcode cr_mime_resume_from(struct Curl_easy *data, curl_off_t passed = 0; do { - char scratch[4*1024]; + char scratch[4 * 1024]; size_t readthisamountnow = (offset - passed > (curl_off_t)sizeof(scratch)) ? sizeof(scratch) : @@ -2267,8 +2243,7 @@ CURLcode curl_mime_encoder(curl_mimepart *part, const char *encoding) return CURLE_NOT_BUILT_IN; } -CURLcode curl_mime_data(curl_mimepart *part, - const char *data, size_t datasize) +CURLcode curl_mime_data(curl_mimepart *part, const char *data, size_t datasize) { (void)part; (void)data; @@ -2283,8 +2258,7 @@ CURLcode curl_mime_filedata(curl_mimepart *part, const char *filename) return CURLE_NOT_BUILT_IN; } -CURLcode curl_mime_data_cb(curl_mimepart *part, - curl_off_t datasize, +CURLcode curl_mime_data_cb(curl_mimepart *part, curl_off_t datasize, curl_read_callback readfunc, curl_seek_callback seekfunc, curl_free_callback freefunc, diff --git a/lib/mime.h b/lib/mime.h index 5073a38f709a..3ac196180bff 100644 --- a/lib/mime.h +++ b/lib/mime.h @@ -165,12 +165,11 @@ CURLcode Curl_creader_set_mime(struct Curl_easy *data, curl_mimepart *part); /* if disabled */ #define Curl_mime_initpart(x) #define Curl_mime_cleanpart(x) -#define Curl_mime_duppart(x,y,z) CURLE_OK /* Nothing to duplicate. Succeed */ -#define Curl_mime_set_subparts(a,b,c) CURLE_NOT_BUILT_IN -#define Curl_mime_prepare_headers(a,b,c,d,e) CURLE_NOT_BUILT_IN -#define Curl_mime_read NULL -#define Curl_creader_set_mime(x,y) ((void)x, CURLE_NOT_BUILT_IN) +#define Curl_mime_duppart(x, y, z) CURLE_OK /* Nothing to duplicate. Succeed */ +#define Curl_mime_set_subparts(a, b, c) CURLE_NOT_BUILT_IN +#define Curl_mime_prepare_headers(a, b, c, d, e) CURLE_NOT_BUILT_IN +#define Curl_mime_read NULL +#define Curl_creader_set_mime(x, y) ((void)x, CURLE_NOT_BUILT_IN) #endif - #endif /* HEADER_CURL_MIME_H */ diff --git a/lib/mprintf.c b/lib/mprintf.c index 176f8a3e4b78..39f45901ed64 100644 --- a/lib/mprintf.c +++ b/lib/mprintf.c @@ -23,14 +23,11 @@ */ #include "curl_setup.h" + #include "curlx/dynbuf.h" #include "curl_printf.h" #include "curlx/strparse.h" -#include "curl_memory.h" -/* The last #include file should be: */ -#include "memdebug.h" - #ifdef HAVE_LONGLONG # define LONG_LONG_TYPE long long # define HAVE_LONG_LONG_TYPE @@ -175,8 +172,8 @@ static int dollarstring(const char *p, const char **end) return (int)num - 1; } -#define is_arg_used(x,y) ((x)[(y)/8] & (1 << ((y)&7))) -#define mark_arg_used(x,y) ((x)[y/8] |= (unsigned char)(1 << ((y)&7))) +#define is_arg_used(x, y) ((x)[(y) / 8] & (1 << ((y) & 7))) +#define mark_arg_used(x, y) ((x)[y / 8] |= (unsigned char)(1 << ((y) & 7))) /* * Parse the format string. @@ -210,7 +207,7 @@ static int parsefmt(const char *format, int max_param = -1; int i; int ocount = 0; - unsigned char usedinput[MAX_PARAMETERS/8]; + unsigned char usedinput[MAX_PARAMETERS / 8]; size_t outlen = 0; struct outsegment *optr; int use_dollar = DOLLAR_UNKNOWN; @@ -368,8 +365,15 @@ static int parsefmt(const char *format, if(!(flags & FLAGS_LEFT)) flags |= FLAGS_PAD_NIL; FALLTHROUGH(); - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': { + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { curl_off_t num; flags |= FLAGS_WIDTH; fmt--; @@ -435,7 +439,7 @@ static int parsefmt(const char *format, type = FORMAT_LONGU; else type = FORMAT_INTU; - flags |= FLAGS_OCTAL|FLAGS_UNSIGNED; + flags |= FLAGS_OCTAL | FLAGS_UNSIGNED; break; case 'x': if(flags & FLAGS_LONGLONG) @@ -444,7 +448,7 @@ static int parsefmt(const char *format, type = FORMAT_LONGU; else type = FORMAT_INTU; - flags |= FLAGS_HEX|FLAGS_UNSIGNED; + flags |= FLAGS_HEX | FLAGS_UNSIGNED; break; case 'X': if(flags & FLAGS_LONGLONG) @@ -453,7 +457,7 @@ static int parsefmt(const char *format, type = FORMAT_LONGU; else type = FORMAT_INTU; - flags |= FLAGS_HEX|FLAGS_UPPER|FLAGS_UNSIGNED; + flags |= FLAGS_HEX | FLAGS_UPPER | FLAGS_UNSIGNED; break; case 'c': type = FORMAT_INT; @@ -468,7 +472,7 @@ static int parsefmt(const char *format, break; case 'E': type = FORMAT_DOUBLE; - flags |= FLAGS_FLOATE|FLAGS_UPPER; + flags |= FLAGS_FLOATE | FLAGS_UPPER; break; case 'g': type = FORMAT_DOUBLE; @@ -476,7 +480,7 @@ static int parsefmt(const char *format, break; case 'G': type = FORMAT_DOUBLE; - flags |= FLAGS_FLOATG|FLAGS_UPPER; + flags |= FLAGS_FLOATG | FLAGS_UPPER; break; default: /* invalid instruction, disregard and continue */ @@ -631,9 +635,9 @@ static bool out_double(void *userp, double dnum, char *work, int *donep) { - char formatbuf[32]="%"; + char formatbuf[32] = "%"; char *fptr = &formatbuf[1]; - size_t left = sizeof(formatbuf)-strlen(formatbuf); + size_t left = sizeof(formatbuf) - strlen(formatbuf); int flags = p->flags; int width = p->width; int prec = p->prec; @@ -749,7 +753,7 @@ static bool out_number(void *userp, if(!(flags & FLAGS_LEFT)) while(--width > 0) OUTCHAR(' '); - OUTCHAR((char) num); + OUTCHAR((char)num); if(flags & FLAGS_LEFT) while(--width > 0) OUTCHAR(' '); @@ -872,7 +876,7 @@ static bool out_string(void *userp, if(!str) { /* Write null string if there is space. */ - if(prec == -1 || prec >= (int) sizeof(nilstr) - 1) { + if(prec == -1 || prec >= (int)sizeof(nilstr) - 1) { str = nilstr; len = sizeof(nilstr) - 1; /* Disable quotes around (nil) */ @@ -920,10 +924,10 @@ static bool out_pointer(void *userp, { /* Generic pointer. */ if(ptr) { - size_t num = (size_t) ptr; + size_t num = (size_t)ptr; /* If the pointer is not NULL, write it as a %#x spec. */ - p->flags |= FLAGS_HEX|FLAGS_ALT; + p->flags |= FLAGS_HEX | FLAGS_ALT; if(out_number(userp, stream, p, num, 0, work, donep)) return TRUE; } @@ -962,13 +966,12 @@ static bool out_pointer(void *userp, * 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)(unsigned char, void *), - const char *format, /* %-formatted string */ - va_list ap_save) /* list of parameters */ +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)(unsigned char, void *), + const char *format, /* %-formatted string */ + va_list ap_save) /* list of parameters */ { int done = 0; /* number of characters written */ int i; @@ -1069,15 +1072,15 @@ static int formatf( /* Answer the count of characters written. */ #ifdef HAVE_LONG_LONG_TYPE if(p.flags & FLAGS_LONGLONG) - *(LONG_LONG_TYPE *) iptr->val.ptr = (LONG_LONG_TYPE)done; + *(LONG_LONG_TYPE *)iptr->val.ptr = (LONG_LONG_TYPE)done; else #endif if(p.flags & FLAGS_LONG) - *(long *) iptr->val.ptr = (long)done; + *(long *)iptr->val.ptr = (long)done; else if(!(p.flags & FLAGS_SHORT)) - *(int *) iptr->val.ptr = (int)done; + *(int *)iptr->val.ptr = (int)done; else - *(short *) iptr->val.ptr = (short)done; + *(short *)iptr->val.ptr = (short)done; break; default: @@ -1142,7 +1145,7 @@ static int alloc_addbyter(unsigned char outc, void *f) CURLcode result = curlx_dyn_addn(infop->b, &outc, 1); if(result) { infop->merr = result == CURLE_TOO_LARGE ? MERR_TOO_LARGE : MERR_MEM; - return 1 ; /* fail */ + return 1; /* fail */ } return 0; } @@ -1177,7 +1180,7 @@ char *curl_mvaprintf(const char *format, va_list ap_save) } if(curlx_dyn_len(info.b)) return curlx_dyn_ptr(info.b); - return strdup(""); + return curlx_strdup(""); } char *curl_maprintf(const char *format, ...) diff --git a/lib/mqtt.c b/lib/mqtt.c index c76ce0a229b7..bc9671cc1796 100644 --- a/lib/mqtt.c +++ b/lib/mqtt.c @@ -28,23 +28,16 @@ #ifndef CURL_DISABLE_MQTT #include "urldata.h" -#include #include "transfer.h" #include "sendf.h" +#include "curl_trc.h" #include "progress.h" #include "mqtt.h" #include "select.h" -#include "strdup.h" #include "url.h" #include "escape.h" -#include "curlx/warnless.h" -#include "multiif.h" #include "rand.h" -/* The last 2 #includes file should be: */ -#include "curl_memory.h" -#include "memdebug.h" - /* first byte is command. second byte is for flags. */ #define MQTT_MSG_CONNECT 0x10 @@ -56,8 +49,8 @@ /* #define MQTT_MSG_PINGREQ 0xC0 */ #define MQTT_MSG_PINGRESP 0xD0 -#define MQTT_CONNACK_LEN 2 -#define MQTT_SUBACK_LEN 3 +#define MQTT_CONNACK_LEN 2 +#define MQTT_SUBACK_LEN 3 #define MQTT_CLIENTID_LEN 12 /* "curl0123abcd" */ /* meta key for storing protocol meta at easy handle */ @@ -97,7 +90,6 @@ struct MQTT { BIT(pingsent); /* 1 while we wait for ping response */ }; - /* * Forward declarations. */ @@ -147,14 +139,14 @@ static void mqtt_easy_dtor(void *key, size_t klen, void *entry) (void)klen; curlx_dyn_free(&mq->sendbuf); curlx_dyn_free(&mq->recvbuf); - free(mq); + curlx_free(mq); } static void mqtt_conn_dtor(void *key, size_t klen, void *entry) { (void)key; (void)klen; - free(entry); + curlx_free(entry); } static CURLcode mqtt_setup_conn(struct Curl_easy *data, @@ -164,12 +156,12 @@ static CURLcode mqtt_setup_conn(struct Curl_easy *data, struct mqtt_conn *mqtt; struct MQTT *mq; - mqtt = calloc(1, sizeof(*mqtt)); + mqtt = curlx_calloc(1, sizeof(*mqtt)); if(!mqtt || Curl_conn_meta_set(conn, CURL_META_MQTT_CONN, mqtt, mqtt_conn_dtor)) return CURLE_OUT_OF_MEMORY; - mq = calloc(1, sizeof(struct MQTT)); + mq = curlx_calloc(1, sizeof(struct MQTT)); if(!mq) return CURLE_OUT_OF_MEMORY; curlx_dyn_init(&mq->recvbuf, DYN_MQTT_RECV); @@ -192,8 +184,8 @@ static CURLcode mqtt_send(struct Curl_easy *data, result = Curl_xfer_send(data, buf, len, FALSE, &n); if(result) return result; - mq->lastTime = curlx_now(); - Curl_debug(data, CURLINFO_HEADER_OUT, buf, (size_t)n); + mq->lastTime = *Curl_pgrs_now(data); + Curl_debug(data, CURLINFO_HEADER_OUT, buf, n); if(len != n) { size_t nsend = len - n; if(curlx_dyn_len(&mq->sendbuf)) { @@ -320,7 +312,7 @@ static CURLcode mqtt_connect(struct Curl_easy *data) int rc = 0; /* remain length */ int remain_pos = 0; - char remain[4] = {0}; + char remain[4] = { 0 }; size_t packetlen = 0; size_t start_user = 0; size_t start_pwd = 0; @@ -329,12 +321,10 @@ static CURLcode mqtt_connect(struct Curl_easy *data) char *packet = NULL; /* extracting username from request */ - const char *username = data->state.aptr.user ? - data->state.aptr.user : ""; + const char *username = data->state.aptr.user ? data->state.aptr.user : ""; const size_t ulen = strlen(username); /* extracting password from request */ - const char *passwd = data->state.aptr.passwd ? - data->state.aptr.passwd : ""; + const char *passwd = data->state.aptr.passwd ? data->state.aptr.passwd : ""; const size_t plen = strlen(passwd); const size_t payloadlen = ulen + plen + MQTT_CLIENTID_LEN + 2 + /* The plus 2s below are for the MSB and LSB describing the length of the @@ -351,7 +341,7 @@ static CURLcode mqtt_connect(struct Curl_easy *data) /* allocating packet */ if(packetlen > 0xFFFFFFF) return CURLE_WEIRD_SERVER_REPLY; - packet = calloc(1, packetlen); + packet = curlx_calloc(1, packetlen); if(!packet) return CURLE_OUT_OF_MEMORY; @@ -401,7 +391,7 @@ static CURLcode mqtt_connect(struct Curl_easy *data) end: if(packet) - free(packet); + curlx_free(packet); Curl_safefree(data->state.aptr.user); Curl_safefree(data->state.aptr.passwd); return result; @@ -525,7 +515,7 @@ static CURLcode mqtt_subscribe(struct Curl_easy *data) n = mqtt_encode_len((char *)encodedsize, packetlen); packetlen += n + 1; /* add one for the control packet type byte */ - packet = malloc(packetlen); + packet = curlx_malloc(packetlen); if(!packet) { result = CURLE_OUT_OF_MEMORY; goto fail; @@ -536,15 +526,15 @@ static CURLcode mqtt_subscribe(struct Curl_easy *data) packet[1 + n] = (mqtt->packetid >> 8) & 0xff; packet[2 + n] = mqtt->packetid & 0xff; packet[3 + n] = (topiclen >> 8) & 0xff; - packet[4 + n ] = topiclen & 0xff; + packet[4 + n] = topiclen & 0xff; memcpy(&packet[5 + n], topic, topiclen); packet[5 + n + topiclen] = 0; /* QoS zero */ result = mqtt_send(data, (const char *)packet, packetlen); fail: - free(topic); - free(packet); + curlx_free(topic); + curlx_free(packet); return result; } @@ -583,6 +573,8 @@ static CURLcode mqtt_verify_suback(struct Curl_easy *data) return result; } +#define MAX_MQTT_MESSAGE_SIZE 0xFFFFFFF + static CURLcode mqtt_publish(struct Curl_easy *data) { CURLcode result; @@ -601,10 +593,11 @@ static CURLcode mqtt_publish(struct Curl_easy *data) DEBUGF(infof(data, "mqtt_publish without payload, return bad arg")); return CURLE_BAD_FUNCTION_ARGUMENT; } - if(postfieldsize < 0) + if(!curlx_sotouz_fits(postfieldsize, &payloadlen)) { + if(postfieldsize > 0) /* off_t does not fit into size_t */ + return CURLE_BAD_FUNCTION_ARGUMENT; payloadlen = strlen(payload); - else - payloadlen = (size_t)postfieldsize; + } result = mqtt_get_topic(data, &topic, &topiclen); if(result) @@ -612,9 +605,13 @@ static CURLcode mqtt_publish(struct Curl_easy *data) remaininglength = payloadlen + 2 + topiclen; encodelen = mqtt_encode_len(encodedbytes, remaininglength); + if(MAX_MQTT_MESSAGE_SIZE - remaininglength - 1 < encodelen) { + result = CURLE_TOO_LARGE; + goto fail; + } /* add the control byte and the encoded remaining length */ - pkt = malloc(remaininglength + 1 + encodelen); + pkt = curlx_malloc(remaininglength + 1 + encodelen); if(!pkt) { result = CURLE_OUT_OF_MEMORY; goto fail; @@ -633,8 +630,8 @@ static CURLcode mqtt_publish(struct Curl_easy *data) result = mqtt_send(data, (const char *)pkt, i); fail: - free(pkt); - free(topic); + curlx_free(pkt); + curlx_free(topic); return result; } @@ -659,7 +656,7 @@ static size_t mqtt_decode_len(unsigned char *buf, } #ifdef DEBUGBUILD -static const char *statenames[]={ +static const char *statenames[] = { "MQTT_FIRST", "MQTT_REMAINING_LENGTH", "MQTT_CONNACK", @@ -693,7 +690,6 @@ static void mqstate(struct Curl_easy *data, mqtt->nextstate = nextstate; } - static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done) { CURLcode result = CURLE_OK; @@ -754,7 +750,7 @@ static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done) FALLTHROUGH(); case MQTT_PUB_REMAIN: { /* read rest of packet, but no more. Cap to buffer size */ - char buffer[4*1024]; + char buffer[4 * 1024]; size_t rest = mq->npacket; if(rest > sizeof(buffer)) rest = sizeof(buffer); @@ -772,7 +768,7 @@ static CURLcode mqtt_read_publish(struct Curl_easy *data, bool *done) } /* we received something */ - mq->lastTime = curlx_now(); + mq->lastTime = *Curl_pgrs_now(data); /* if QoS is set, message contains packet id */ result = Curl_client_write(data, CLIENTWRITE_BODY, buffer, nread); @@ -802,7 +798,7 @@ static CURLcode mqtt_do(struct Curl_easy *data, bool *done) if(!mq) return CURLE_FAILED_INIT; - mq->lastTime = curlx_now(); + mq->lastTime = *Curl_pgrs_now(data); mq->pingsent = FALSE; result = mqtt_connect(data); @@ -841,8 +837,8 @@ static CURLcode mqtt_ping(struct Curl_easy *data) if(mqtt->state == MQTT_FIRST && !mq->pingsent && data->set.upkeep_interval_ms > 0) { - struct curltime t = curlx_now(); - timediff_t diff = curlx_timediff(t, mq->lastTime); + struct curltime t = *Curl_pgrs_now(data); + timediff_t diff = curlx_ptimediff_ms(&t, &mq->lastTime); if(diff > data->set.upkeep_interval_ms) { /* 0xC0 is PINGREQ, and 0x00 is remaining length */ @@ -884,7 +880,7 @@ static CURLcode mqtt_doing(struct Curl_easy *data, bool *done) if(result) return result; - infof(data, "mqtt_doing: state [%d]", (int) mqtt->state); + infof(data, "mqtt_doing: state [%d]", (int)mqtt->state); switch(mqtt->state) { case MQTT_FIRST: /* Read the initial byte only */ @@ -900,7 +896,7 @@ static CURLcode mqtt_doing(struct Curl_easy *data, bool *done) Curl_debug(data, CURLINFO_HEADER_IN, (const char *)&mq->firstbyte, 1); /* we received something */ - mq->lastTime = curlx_now(); + mq->lastTime = *Curl_pgrs_now(data); /* remember the first byte */ mq->npacket = 0; diff --git a/lib/multi.c b/lib/multi.c index ca7c1bdd9542..7c03de20a2a2 100644 --- a/lib/multi.c +++ b/lib/multi.c @@ -24,26 +24,22 @@ #include "curl_setup.h" -#include - #include "urldata.h" #include "transfer.h" #include "url.h" #include "cfilters.h" #include "connect.h" #include "progress.h" -#include "easyif.h" -#include "share.h" +#include "curl_share.h" #include "psl.h" #include "multiif.h" #include "multi_ev.h" #include "sendf.h" +#include "curl_trc.h" #include "curlx/timeval.h" #include "http.h" #include "select.h" -#include "curlx/warnless.h" #include "curlx/wait.h" -#include "speedcheck.h" #include "conncache.h" #include "multihandle.h" #include "sigpipe.h" @@ -52,15 +48,10 @@ #include "http_proxy.h" #include "http2.h" #include "socketpair.h" -#include "socks.h" -#include "urlapi-int.h" - -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" +#include "bufref.h" /* initial multi->xfers table size for a full multi */ -#define CURL_XFER_TABLE_SIZE 512 +#define CURL_XFER_TABLE_SIZE 512 /* CURL_SOCKET_HASH_TABLE_SIZE should be a prime number. Increasing it from 97 @@ -85,6 +76,7 @@ #define CURL_MULTI_HANDLE 0x000bab1e + #ifdef DEBUGBUILD /* On a debug build, we want to fail hard on multi handles that * are not NULL, but no longer have the MAGIC touch. This gives @@ -99,18 +91,24 @@ static void move_pending_to_connect(struct Curl_multi *multi, struct Curl_easy *data); -static CURLMcode add_next_timeout(struct curltime now, +static CURLMcode add_next_timeout(const struct curltime *pnow, struct Curl_multi *multi, struct Curl_easy *d); -static CURLMcode multi_timeout(struct Curl_multi *multi, - struct curltime *expire_time, - long *timeout_ms); +static void multi_timeout(struct Curl_multi *multi, + struct curltime *expire_time, + long *timeout_ms); static void process_pending_handles(struct Curl_multi *multi); static void multi_xfer_bufs_free(struct Curl_multi *multi); #ifdef DEBUGBUILD static void multi_xfer_tbl_dump(struct Curl_multi *multi); #endif +static const struct curltime *multi_now(struct Curl_multi *multi) +{ + curlx_pnow(&multi->now); + return &multi->now; +} + /* function pointer called once when switching TO a state */ typedef void (*init_multistate_func)(struct Curl_easy *data); @@ -146,7 +144,6 @@ static void mstate(struct Curl_easy *data, CURLMstate state Curl_init_CONNECT, /* CONNECT */ NULL, /* RESOLVING */ NULL, /* CONNECTING */ - NULL, /* TUNNELING */ NULL, /* PROTOCONNECT */ NULL, /* PROTOCONNECTING */ NULL, /* DO */ @@ -170,6 +167,7 @@ static void mstate(struct Curl_easy *data, CURLMstate state CURL_TRC_M(data, "-> [%s]", CURL_MSTATE_NAME(state)); #endif + /* really switching state */ data->mstate = state; switch(state) { case MSTATE_DONE: @@ -181,11 +179,11 @@ static void mstate(struct Curl_easy *data, CURLMstate state if(oldstate < MSTATE_DONE) CURLM_NTFY(data, CURLMNOTIFY_EASY_DONE); /* changing to COMPLETED means it is in process and needs to go */ - DEBUGASSERT(Curl_uint_bset_contains(&data->multi->process, data->mid)); - Curl_uint_bset_remove(&data->multi->process, data->mid); - Curl_uint_bset_remove(&data->multi->pending, data->mid); /* to be sure */ + DEBUGASSERT(Curl_uint32_bset_contains(&data->multi->process, data->mid)); + Curl_uint32_bset_remove(&data->multi->process, data->mid); + Curl_uint32_bset_remove(&data->multi->pending, data->mid); /* to be sure */ - if(Curl_uint_bset_empty(&data->multi->process)) { + if(Curl_uint32_bset_empty(&data->multi->process)) { /* free the transfer buffer when we have no more active transfers */ multi_xfer_bufs_free(data->multi); } @@ -200,12 +198,11 @@ static void mstate(struct Curl_easy *data, CURLMstate state } #ifndef DEBUGBUILD -#define multistate(x,y) mstate(x,y) +#define multistate(x, y) mstate(x, y) #else -#define multistate(x,y) mstate(x,y, __LINE__) +#define multistate(x, y) mstate(x, y, __LINE__) #endif - /* multi->proto_hash destructor. Should never be called as elements * MUST be added with their own destructor */ static void ph_freeentry(void *p) @@ -230,13 +227,13 @@ static void multi_addmsg(struct Curl_multi *multi, struct Curl_message *msg) Curl_llist_append(&multi->msglist, msg, &msg->list); } -struct Curl_multi *Curl_multi_handle(unsigned int xfer_table_size, +struct Curl_multi *Curl_multi_handle(uint32_t xfer_table_size, size_t ev_hashsize, /* event hash */ size_t chashsize, /* connection hash */ size_t dnssize, /* dns hash */ size_t sesssize) /* TLS session cache */ { - struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi)); + struct Curl_multi *multi = curlx_calloc(1, sizeof(struct Curl_multi)); if(!multi) return NULL; @@ -246,11 +243,11 @@ struct Curl_multi *Curl_multi_handle(unsigned int xfer_table_size, Curl_dnscache_init(&multi->dnscache, dnssize); Curl_mntfy_init(multi); Curl_multi_ev_init(multi, ev_hashsize); - Curl_uint_tbl_init(&multi->xfers, NULL); - Curl_uint_bset_init(&multi->process); - Curl_uint_bset_init(&multi->dirty); - Curl_uint_bset_init(&multi->pending); - Curl_uint_bset_init(&multi->msgsent); + Curl_uint32_tbl_init(&multi->xfers, NULL); + Curl_uint32_bset_init(&multi->process); + Curl_uint32_bset_init(&multi->dirty); + Curl_uint32_bset_init(&multi->pending); + Curl_uint32_bset_init(&multi->msgsent); Curl_hash_init(&multi->proto_hash, 23, Curl_hash_str, curlx_str_key_compare, ph_freeentry); Curl_llist_init(&multi->msglist, NULL); @@ -260,11 +257,11 @@ struct Curl_multi *Curl_multi_handle(unsigned int xfer_table_size, multi->last_timeout_ms = -1; if(Curl_mntfy_resize(multi) || - Curl_uint_bset_resize(&multi->process, xfer_table_size) || - Curl_uint_bset_resize(&multi->pending, xfer_table_size) || - Curl_uint_bset_resize(&multi->dirty, xfer_table_size) || - Curl_uint_bset_resize(&multi->msgsent, xfer_table_size) || - Curl_uint_tbl_resize(&multi->xfers, xfer_table_size)) + Curl_uint32_bset_resize(&multi->process, xfer_table_size) || + Curl_uint32_bset_resize(&multi->pending, xfer_table_size) || + Curl_uint32_bset_resize(&multi->dirty, xfer_table_size) || + Curl_uint32_bset_resize(&multi->msgsent, xfer_table_size) || + Curl_uint32_tbl_resize(&multi->xfers, xfer_table_size)) goto error; multi->admin = curl_easy_init(); @@ -274,11 +271,13 @@ struct Curl_multi *Curl_multi_handle(unsigned int xfer_table_size, multi->admin->multi = multi; multi->admin->state.internal = TRUE; Curl_llist_init(&multi->admin->state.timeoutlist, NULL); + #ifdef DEBUGBUILD if(getenv("CURL_DEBUG")) multi->admin->set.verbose = TRUE; #endif - Curl_uint_tbl_add(&multi->xfers, multi->admin, &multi->admin->mid); + Curl_uint32_tbl_add(&multi->xfers, multi->admin, &multi->admin->mid); + Curl_uint32_bset_add(&multi->process, multi->admin->mid); if(Curl_cshutdn_init(&multi->cshutdn, multi)) goto error; @@ -321,13 +320,13 @@ struct Curl_multi *Curl_multi_handle(unsigned int xfer_table_size, } Curl_mntfy_cleanup(multi); - Curl_uint_bset_destroy(&multi->process); - Curl_uint_bset_destroy(&multi->dirty); - Curl_uint_bset_destroy(&multi->pending); - Curl_uint_bset_destroy(&multi->msgsent); - Curl_uint_tbl_destroy(&multi->xfers); + Curl_uint32_bset_destroy(&multi->process); + Curl_uint32_bset_destroy(&multi->dirty); + Curl_uint32_bset_destroy(&multi->pending); + Curl_uint32_bset_destroy(&multi->msgsent); + Curl_uint32_tbl_destroy(&multi->xfers); - free(multi); + curlx_free(multi); return NULL; } @@ -346,24 +345,23 @@ static void multi_warn_debug(struct Curl_multi *multi, struct Curl_easy *data) if(!multi->warned) { infof(data, "!!! WARNING !!!"); infof(data, "This is a debug build of libcurl, " - "do not use in production."); + "do not use in production."); multi->warned = TRUE; } } #else -#define multi_warn_debug(x,y) Curl_nop_stmt +#define multi_warn_debug(x, y) Curl_nop_stmt #endif - static CURLMcode multi_xfers_add(struct Curl_multi *multi, struct Curl_easy *data) { - unsigned int capacity = Curl_uint_tbl_capacity(&multi->xfers); - unsigned int new_size = 0; + uint32_t capacity = Curl_uint32_tbl_capacity(&multi->xfers); + uint32_t new_size = 0; /* Prepare to make this into a CURLMOPT_MAX_TRANSFERS, because some * applications may want to prevent a run-away of their memory use. */ /* UINT_MAX is our "invalid" id, do not let the table grow up to that. */ - const unsigned int max_capacity = UINT_MAX - 1; + const uint32_t max_capacity = UINT_MAX - 1; if(capacity < max_capacity) { /* We want `multi->xfers` to have "sufficient" free rows, so that we do @@ -371,9 +369,9 @@ static CURLMcode multi_xfers_add(struct Curl_multi *multi, * Since uint_tbl and uint_bset are quite memory efficient, * regard less than 25% free as insufficient. * (for low capacities, e.g. multi_easy, 4 or less). */ - unsigned int used = Curl_uint_tbl_count(&multi->xfers); - unsigned int unused = capacity - used; - unsigned int min_unused = CURLMAX(capacity >> 2, 4); + uint32_t used = Curl_uint32_tbl_count(&multi->xfers); + uint32_t unused = capacity - used; + uint32_t min_unused = CURLMAX(capacity >> 2, 4); if(unused <= min_unused) { /* Make sure the uint arithmetic here works on the corner * cases where we are close to max_capacity or UINT_MAX */ @@ -383,8 +381,8 @@ static CURLMcode multi_xfers_add(struct Curl_multi *multi, new_size = max_capacity; /* can not be larger than this */ } else { - /* make it a 64 multiple, since our bitsets frow by that and - * small (easy_multi) grows to at least 64 on first resize. */ + /* make it a 64 multiple, since our bitsets frow by that and + * small (easy_multi) grows to at least 64 on first resize. */ new_size = (((used + min_unused) + 63) / 64) * 64; } } @@ -396,30 +394,30 @@ static CURLMcode multi_xfers_add(struct Curl_multi *multi, * to work properly when larger than the table, but not * the other way around. */ CURL_TRC_M(data, "increasing xfer table size to %u", new_size); - if(Curl_uint_bset_resize(&multi->process, new_size) || - Curl_uint_bset_resize(&multi->dirty, new_size) || - Curl_uint_bset_resize(&multi->pending, new_size) || - Curl_uint_bset_resize(&multi->msgsent, new_size) || - Curl_uint_tbl_resize(&multi->xfers, new_size)) + if(Curl_uint32_bset_resize(&multi->process, new_size) || + Curl_uint32_bset_resize(&multi->dirty, new_size) || + Curl_uint32_bset_resize(&multi->pending, new_size) || + Curl_uint32_bset_resize(&multi->msgsent, new_size) || + Curl_uint32_tbl_resize(&multi->xfers, new_size)) return CURLM_OUT_OF_MEMORY; } /* Insert the easy into the table now */ - if(!Curl_uint_tbl_add(&multi->xfers, data, &data->mid)) { + if(!Curl_uint32_tbl_add(&multi->xfers, data, &data->mid)) { /* MUST only happen when table is full */ - DEBUGASSERT(Curl_uint_tbl_capacity(&multi->xfers) <= - Curl_uint_tbl_count(&multi->xfers)); + DEBUGASSERT(Curl_uint32_tbl_capacity(&multi->xfers) <= + Curl_uint32_tbl_count(&multi->xfers)); return CURLM_OUT_OF_MEMORY; } return CURLM_OK; } - CURLMcode curl_multi_add_handle(CURLM *m, CURL *d) { - CURLMcode rc; + CURLMcode mresult; struct Curl_multi *multi = m; struct Curl_easy *data = d; + /* First, make some basic checks that the CURLM handle is a good handle */ if(!GOOD_MULTI_HANDLE(multi)) return CURLM_BAD_HANDLE; @@ -441,14 +439,14 @@ CURLMcode curl_multi_add_handle(CURLM *m, CURL *d) handles are still alive - but if there are none alive anymore, it is fine to start over and unmark the "deadness" of this handle. This means only the admin handle MUST be present. */ - if((Curl_uint_tbl_count(&multi->xfers) != 1) || - !Curl_uint_tbl_contains(&multi->xfers, 0)) + if((Curl_uint32_tbl_count(&multi->xfers) != 1) || + !Curl_uint32_tbl_contains(&multi->xfers, 0)) return CURLM_ABORTED_BY_CALLBACK; multi->dead = FALSE; - Curl_uint_bset_clear(&multi->process); - Curl_uint_bset_clear(&multi->dirty); - Curl_uint_bset_clear(&multi->pending); - Curl_uint_bset_clear(&multi->msgsent); + Curl_uint32_bset_clear(&multi->process); + Curl_uint32_bset_clear(&multi->dirty); + Curl_uint32_bset_clear(&multi->pending); + Curl_uint32_bset_clear(&multi->msgsent); } if(data->multi_easy) { @@ -492,7 +490,7 @@ CURLMcode curl_multi_add_handle(CURLM *m, CURL *d) #endif /* add the easy handle to the process set */ - Curl_uint_bset_add(&multi->process, data->mid); + Curl_uint32_bset_add(&multi->process, data->mid); ++multi->xfers_alive; ++multi->xfers_total_ever; @@ -501,14 +499,15 @@ CURLMcode curl_multi_add_handle(CURLM *m, CURL *d) /* Make sure the new handle will run */ Curl_multi_mark_dirty(data); + /* Necessary in event based processing, where dirty handles trigger * a timeout callback invocation. */ - rc = Curl_update_timer(multi); - if(rc) { + mresult = Curl_update_timer(multi); + if(mresult) { data->multi = NULL; /* not anymore */ - Curl_uint_tbl_remove(&multi->xfers, data->mid); - data->mid = UINT_MAX; - return rc; + Curl_uint32_tbl_remove(&multi->xfers, data->mid); + data->mid = UINT32_MAX; + return mresult; } /* The admin handle only ever has default timeouts set. To improve the @@ -522,7 +521,7 @@ CURLMcode curl_multi_add_handle(CURLM *m, CURL *d) CURL_TRC_M(data, "added to multi, mid=%u, running=%u, total=%u", data->mid, Curl_multi_xfers_running(multi), - Curl_uint_tbl_count(&multi->xfers)); + Curl_uint32_tbl_count(&multi->xfers)); return CURLM_OK; } @@ -546,6 +545,47 @@ struct multi_done_ctx { BIT(premature); }; +static bool multi_conn_should_close(struct connectdata *conn, + struct Curl_easy *data, + bool premature) +{ + /* if conn->bits.close is TRUE, it means that the connection should be + closed in spite of everything else. */ + if(conn->bits.close) + return TRUE; + + /* if data->set.reuse_forbid is TRUE, it means the libcurl client has + forced us to close this connection. This is ignored for requests taking + place in a NTLM/NEGOTIATE authentication handshake. */ + if(data->set.reuse_forbid +#ifdef USE_NTLM + && !(conn->http_ntlm_state == NTLMSTATE_TYPE2 || + conn->proxy_ntlm_state == NTLMSTATE_TYPE2) +#endif +#ifdef USE_SPNEGO + && !(conn->http_negotiate_state == GSS_AUTHRECV || + conn->proxy_negotiate_state == GSS_AUTHRECV) +#endif + ) + return TRUE; + + /* Unless this connection is for a "connect-only" transfer, it + * needs to be closed if the protocol handler does not support reuse. */ + if(!data->set.connect_only && conn->handler && + !(conn->handler->flags & PROTOPT_CONN_REUSE)) + return TRUE; + + /* if premature is TRUE, it means this connection was said to be DONE before + the entire request operation is complete and thus we cannot know in what + state it is for reusing, so we are forced to close it. In a perfect world + we can add code that keep track of if we really must close it here or not, + but currently we have no such detail knowledge. */ + if(premature && !Curl_conn_is_multiplex(conn, FIRSTSOCKET)) + return TRUE; + + return FALSE; +} + static void multi_done_locked(struct connectdata *conn, struct Curl_easy *data, void *userdata) @@ -570,12 +610,11 @@ static void multi_done_locked(struct connectdata *conn, Curl_detach_connection(data); - CURL_TRC_M(data, "multi_done_locked, in use=%u", - Curl_uint_spbset_count(&conn->xfers_attached)); + CURL_TRC_M(data, "multi_done_locked, in use=%u", conn->attached_xfers); if(CONN_INUSE(conn)) { /* Stop if still used. */ CURL_TRC_M(data, "Connection still in use %u, no more multi_done now!", - Curl_uint_spbset_count(&conn->xfers_attached)); + conn->attached_xfers); return; } @@ -586,32 +625,7 @@ static void multi_done_locked(struct connectdata *conn, Curl_resolv_unlink(data, &data->state.dns[1]); Curl_dnscache_prune(data); - /* if data->set.reuse_forbid is TRUE, it means the libcurl client has - forced us to close this connection. This is ignored for requests taking - place in a NTLM/NEGOTIATE authentication handshake - - if conn->bits.close is TRUE, it means that the connection should be - closed in spite of all our efforts to be nice, due to protocol - restrictions in our or the server's end - - if premature is TRUE, it means this connection was said to be DONE before - the entire request operation is complete and thus we cannot know in what - state it is for reusing, so we are forced to close it. In a perfect world - we can add code that keep track of if we really must close it here or not, - but currently we have no such detail knowledge. - */ - - if((data->set.reuse_forbid -#ifdef USE_NTLM - && !(conn->http_ntlm_state == NTLMSTATE_TYPE2 || - conn->proxy_ntlm_state == NTLMSTATE_TYPE2) -#endif -#ifdef USE_SPNEGO - && !(conn->http_negotiate_state == GSS_AUTHRECV || - conn->proxy_negotiate_state == GSS_AUTHRECV) -#endif - ) || conn->bits.close - || (mdctx->premature && !Curl_conn_is_multiplex(conn, FIRSTSOCKET))) { + if(multi_conn_should_close(conn, data, mdctx->premature)) { #ifndef CURL_DISABLE_VERBOSE_STRINGS CURL_TRC_M(data, "multi_done, terminating conn #%" FMT_OFF_T " to %s:%d, " "forbid=%d, close=%d, premature=%d, conn_multiplex=%d", @@ -737,9 +751,9 @@ CURLMcode curl_multi_remove_handle(CURLM *m, CURL *d) struct Curl_easy *data = d; bool premature; struct Curl_llist_node *e; - CURLMcode rc; + CURLMcode mresult; bool removed_timer = FALSE; - unsigned int mid; + uint32_t mid; /* First, make some basic checks that the CURLM handle is a good handle */ if(!GOOD_MULTI_HANDLE(multi)) @@ -757,11 +771,11 @@ CURLMcode curl_multi_remove_handle(CURLM *m, CURL *d) if(data->multi != multi) return CURLM_BAD_EASY_HANDLE; - if(data->mid == UINT_MAX) { + if(data->mid == UINT32_MAX) { DEBUGASSERT(0); return CURLM_INTERNAL_ERROR; } - if(Curl_uint_tbl_get(&multi->xfers, data->mid) != data) { + if(Curl_uint32_tbl_get(&multi->xfers, data->mid) != data) { DEBUGASSERT(0); return CURLM_INTERNAL_ERROR; } @@ -796,7 +810,7 @@ CURLMcode curl_multi_remove_handle(CURLM *m, CURL *d) removed_timer = Curl_expire_clear(data); /* If in `msgsent`, it was deducted from `multi->xfers_alive` already. */ - if(!Curl_uint_bset_contains(&multi->msgsent, data->mid)) + if(!Curl_uint32_bset_contains(&multi->msgsent, data->mid)) --multi->xfers_alive; Curl_wildcard_dtor(&data->wildcard); @@ -829,7 +843,7 @@ CURLMcode curl_multi_remove_handle(CURLM *m, CURL *d) if(data->state.lastconnect_id != -1) { /* Mark any connect-only connection for closure */ Curl_cpool_do_by_id(data, data->state.lastconnect_id, - close_connect_only, NULL); + close_connect_only, NULL); } #ifdef USE_LIBPSL @@ -852,29 +866,29 @@ CURLMcode curl_multi_remove_handle(CURLM *m, CURL *d) /* clear the association to this multi handle */ mid = data->mid; - DEBUGASSERT(Curl_uint_tbl_contains(&multi->xfers, mid)); - Curl_uint_tbl_remove(&multi->xfers, mid); - Curl_uint_bset_remove(&multi->process, mid); - Curl_uint_bset_remove(&multi->dirty, mid); - Curl_uint_bset_remove(&multi->pending, mid); - Curl_uint_bset_remove(&multi->msgsent, mid); + DEBUGASSERT(Curl_uint32_tbl_contains(&multi->xfers, mid)); + Curl_uint32_tbl_remove(&multi->xfers, mid); + Curl_uint32_bset_remove(&multi->process, mid); + Curl_uint32_bset_remove(&multi->dirty, mid); + Curl_uint32_bset_remove(&multi->pending, mid); + Curl_uint32_bset_remove(&multi->msgsent, mid); data->multi = NULL; - data->mid = UINT_MAX; - data->master_mid = UINT_MAX; + data->mid = UINT32_MAX; + data->master_mid = UINT32_MAX; /* NOTE NOTE NOTE We do not touch the easy handle here! */ process_pending_handles(multi); if(removed_timer) { - rc = Curl_update_timer(multi); - if(rc) - return rc; + mresult = Curl_update_timer(multi); + if(mresult) + return mresult; } CURL_TRC_M(data, "removed from multi, mid=%u, running=%u, total=%u", mid, Curl_multi_xfers_running(multi), - Curl_uint_tbl_count(&multi->xfers)); + Curl_uint32_tbl_count(&multi->xfers)); return CURLM_OK; } @@ -894,9 +908,13 @@ void Curl_detach_connection(struct Curl_easy *data) { struct connectdata *conn = data->conn; if(conn) { - Curl_uint_spbset_remove(&conn->xfers_attached, data->mid); - if(Curl_uint_spbset_empty(&conn->xfers_attached)) - conn->attached_multi = NULL; + /* this should never happen, prevent underflow */ + DEBUGASSERT(conn->attached_xfers); + if(conn->attached_xfers) { + conn->attached_xfers--; + if(!conn->attached_xfers) + conn->attached_multi = NULL; + } } data->conn = NULL; } @@ -912,8 +930,9 @@ void Curl_attach_connection(struct Curl_easy *data, DEBUGASSERT(data); DEBUGASSERT(!data->conn); DEBUGASSERT(conn); + DEBUGASSERT(conn->attached_xfers < UINT32_MAX); data->conn = conn; - Curl_uint_spbset_add(&conn->xfers_attached, data->mid); + conn->attached_xfers++; /* all attached transfers must be from the same multi */ if(!conn->attached_multi) conn->attached_multi = data->multi; @@ -923,102 +942,168 @@ void Curl_attach_connection(struct Curl_easy *data, conn->handler->attach(data, conn); } +/* adjust pollset for rate limits/pauses */ +static CURLcode multi_adjust_pollset(struct Curl_easy *data, + struct easy_pollset *ps) +{ + CURLcode result = CURLE_OK; + + if(ps->n) { + const struct curltime *pnow = Curl_pgrs_now(data); + bool send_blocked, recv_blocked; + + recv_blocked = (Curl_rlimit_avail(&data->progress.dl.rlimit, pnow) <= 0); + send_blocked = (Curl_rlimit_avail(&data->progress.ul.rlimit, pnow) <= 0); + if(send_blocked || recv_blocked) { + int i; + for(i = 0; i <= SECONDARYSOCKET; ++i) { + curl_socket_t sock = data->conn->sock[i]; + if(sock == CURL_SOCKET_BAD) + continue; + if(recv_blocked && Curl_pollset_want_recv(data, ps, sock)) { + result = Curl_pollset_remove_in(data, ps, sock); + if(result) + break; + } + if(send_blocked && Curl_pollset_want_send(data, ps, sock)) { + result = Curl_pollset_remove_out(data, ps, sock); + if(result) + break; + } + } + } + + /* Not blocked and wanting to receive. If there is data pending + * in the connection filters, make transfer run again. */ + if(!recv_blocked && + ((Curl_pollset_want_recv(data, ps, data->conn->sock[FIRSTSOCKET]) && + Curl_conn_data_pending(data, FIRSTSOCKET)) || + (Curl_pollset_want_recv(data, ps, data->conn->sock[SECONDARYSOCKET]) && + Curl_conn_data_pending(data, SECONDARYSOCKET)))) { + CURL_TRC_M(data, "pollset[] has POLLIN, but there is still " + "buffered input -> mark as dirty"); + Curl_multi_mark_dirty(data); + } + } + return result; +} + static CURLcode mstate_connecting_pollset(struct Curl_easy *data, struct easy_pollset *ps) { - if(data->conn) { - curl_socket_t sockfd = Curl_conn_get_first_socket(data); - if(sockfd != CURL_SOCKET_BAD) { - /* Default is to wait to something from the server */ - return Curl_pollset_change(data, ps, sockfd, CURL_POLL_IN, 0); - } + struct connectdata *conn = data->conn; + curl_socket_t sockfd; + CURLcode result = CURLE_OK; + + if(Curl_xfer_recv_is_paused(data)) + return CURLE_OK; + /* If a socket is set, receiving is default. If the socket + * has not been determined yet (eyeballing), always ask the + * connection filters for what to monitor. */ + sockfd = Curl_conn_get_first_socket(data); + if(sockfd != CURL_SOCKET_BAD) { + result = Curl_pollset_change(data, ps, sockfd, CURL_POLL_IN, 0); + if(!result) + result = multi_adjust_pollset(data, ps); } - return CURLE_OK; + if(!result) + result = Curl_conn_adjust_pollset(data, conn, ps); + return result; } static CURLcode mstate_protocol_pollset(struct Curl_easy *data, struct easy_pollset *ps) { struct connectdata *conn = data->conn; - if(conn) { - curl_socket_t sockfd; - if(conn->handler->proto_pollset) - return conn->handler->proto_pollset(data, ps); - sockfd = conn->sock[FIRSTSOCKET]; + CURLcode result = CURLE_OK; + + if(conn->handler->proto_pollset) + result = conn->handler->proto_pollset(data, ps); + else { + curl_socket_t sockfd = conn->sock[FIRSTSOCKET]; if(sockfd != CURL_SOCKET_BAD) { /* Default is to wait to something from the server */ - return Curl_pollset_change(data, ps, sockfd, CURL_POLL_IN, 0); + result = Curl_pollset_change(data, ps, sockfd, CURL_POLL_IN, 0); } } - return CURLE_OK; + if(!result) + result = multi_adjust_pollset(data, ps); + if(!result) + result = Curl_conn_adjust_pollset(data, conn, ps); + return result; } static CURLcode mstate_do_pollset(struct Curl_easy *data, struct easy_pollset *ps) { struct connectdata *conn = data->conn; - if(conn) { - if(conn->handler->doing_pollset) - return conn->handler->doing_pollset(data, ps); - else if(CONN_SOCK_IDX_VALID(conn->send_idx)) { - /* Default is that we want to send something to the server */ - return Curl_pollset_add_out( - data, ps, conn->sock[conn->send_idx]); - } + CURLcode result = CURLE_OK; + + if(conn->handler->doing_pollset) + result = conn->handler->doing_pollset(data, ps); + else if(CONN_SOCK_IDX_VALID(conn->send_idx)) { + /* Default is that we want to send something to the server */ + result = Curl_pollset_add_out(data, ps, conn->sock[conn->send_idx]); } - return CURLE_OK; + if(!result) + result = multi_adjust_pollset(data, ps); + if(!result) + result = Curl_conn_adjust_pollset(data, conn, ps); + return result; } static CURLcode mstate_domore_pollset(struct Curl_easy *data, struct easy_pollset *ps) { struct connectdata *conn = data->conn; - if(conn) { - if(conn->handler->domore_pollset) - return conn->handler->domore_pollset(data, ps); - else if(CONN_SOCK_IDX_VALID(conn->send_idx)) { - /* Default is that we want to send something to the server */ - return Curl_pollset_add_out( - data, ps, conn->sock[conn->send_idx]); - } + CURLcode result = CURLE_OK; + + if(conn->handler->domore_pollset) + result = conn->handler->domore_pollset(data, ps); + else if(CONN_SOCK_IDX_VALID(conn->send_idx)) { + /* Default is that we want to send something to the server */ + result = Curl_pollset_add_out(data, ps, conn->sock[conn->send_idx]); } - return CURLE_OK; + if(!result) + result = multi_adjust_pollset(data, ps); + if(!result) + result = Curl_conn_adjust_pollset(data, conn, ps); + return result; } static CURLcode mstate_perform_pollset(struct Curl_easy *data, struct easy_pollset *ps) { struct connectdata *conn = data->conn; - if(!conn) - return CURLE_OK; - else if(conn->handler->perform_pollset) - return conn->handler->perform_pollset(data, ps); + CURLcode result = CURLE_OK; + + if(conn->handler->perform_pollset) + result = conn->handler->perform_pollset(data, ps); else { /* Default is to obey the data->req.keepon flags for send/recv */ - CURLcode result = CURLE_OK; if(CURL_WANT_RECV(data) && CONN_SOCK_IDX_VALID(conn->recv_idx)) { - result = Curl_pollset_add_in( - data, ps, conn->sock[conn->recv_idx]); + result = Curl_pollset_add_in(data, ps, conn->sock[conn->recv_idx]); } if(!result && Curl_req_want_send(data) && CONN_SOCK_IDX_VALID(conn->send_idx)) { - result = Curl_pollset_add_out( - data, ps, conn->sock[conn->send_idx]); + result = Curl_pollset_add_out(data, ps, conn->sock[conn->send_idx]); } - return result; } + if(!result) + result = multi_adjust_pollset(data, ps); + if(!result) + result = Curl_conn_adjust_pollset(data, conn, ps); + return result; } /* Initializes `poll_set` with the current socket poll actions needed * for transfer `data`. */ CURLMcode Curl_multi_pollset(struct Curl_easy *data, - struct easy_pollset *ps, - const char *caller) + struct easy_pollset *ps) { CURLMcode mresult = CURLM_OK; CURLcode result = CURLE_OK; - bool expect_sockets = TRUE; /* If the transfer has no connection, this is fine. Happens when called via curl_multi_remove_handle() => Curl_multi_ev_assess() => @@ -1033,70 +1118,48 @@ CURLMcode Curl_multi_pollset(struct Curl_easy *data, case MSTATE_SETUP: case MSTATE_CONNECT: /* nothing to poll for yet */ - expect_sockets = FALSE; break; case MSTATE_RESOLVING: result = Curl_resolv_pollset(data, ps); - /* connection filters are not involved in this phase. It's ok if we get no - * sockets to wait for. Resolving can wake up from other sources. */ - expect_sockets = FALSE; break; case MSTATE_CONNECTING: - case MSTATE_TUNNELING: - if(!Curl_xfer_recv_is_paused(data)) { - result = mstate_connecting_pollset(data, ps); - if(!result) - result = Curl_conn_adjust_pollset(data, data->conn, ps); - } - else - expect_sockets = FALSE; + result = mstate_connecting_pollset(data, ps); break; case MSTATE_PROTOCONNECT: case MSTATE_PROTOCONNECTING: result = mstate_protocol_pollset(data, ps); - if(!result) - result = Curl_conn_adjust_pollset(data, data->conn, ps); break; case MSTATE_DO: case MSTATE_DOING: result = mstate_do_pollset(data, ps); - if(!result) - result = Curl_conn_adjust_pollset(data, data->conn, ps); break; case MSTATE_DOING_MORE: result = mstate_domore_pollset(data, ps); - if(!result) - result = Curl_conn_adjust_pollset(data, data->conn, ps); break; case MSTATE_DID: /* same as PERFORMING in regard to polling */ case MSTATE_PERFORMING: result = mstate_perform_pollset(data, ps); - if(!result) - result = Curl_conn_adjust_pollset(data, data->conn, ps); break; case MSTATE_RATELIMITING: /* we need to let time pass, ignore socket(s) */ - expect_sockets = FALSE; break; case MSTATE_DONE: case MSTATE_COMPLETED: case MSTATE_MSGSENT: /* nothing more to poll for */ - expect_sockets = FALSE; break; default: failf(data, "multi_getsock: unexpected multi state %d", data->mstate); DEBUGASSERT(0); - expect_sockets = FALSE; break; } @@ -1110,68 +1173,42 @@ CURLMcode Curl_multi_pollset(struct Curl_easy *data, goto out; } - /* Unblocked and waiting to receive with buffered input. - * Make transfer run again at next opportunity. */ - if(!Curl_xfer_is_blocked(data) && !Curl_xfer_is_too_fast(data) && - ((Curl_pollset_want_read(data, ps, data->conn->sock[FIRSTSOCKET]) && - Curl_conn_data_pending(data, FIRSTSOCKET)) || - (Curl_pollset_want_read(data, ps, data->conn->sock[SECONDARYSOCKET]) && - Curl_conn_data_pending(data, SECONDARYSOCKET)))) { - CURL_TRC_M(data, "%s pollset[] has POLLIN, but there is still " - "buffered input to consume -> mark as dirty", caller); - Curl_multi_mark_dirty(data); - } - #ifndef CURL_DISABLE_VERBOSE_STRINGS if(CURL_TRC_M_is_verbose(data)) { size_t timeout_count = Curl_llist_count(&data->state.timeoutlist); switch(ps->n) { - case 0: - CURL_TRC_M(data, "%s pollset[], timeouts=%zu, paused %d/%d (r/w)", - caller, timeout_count, - Curl_xfer_send_is_paused(data), - Curl_xfer_recv_is_paused(data)); - break; - case 1: - CURL_TRC_M(data, "%s pollset[fd=%" FMT_SOCKET_T " %s%s], timeouts=%zu", - caller, ps->sockets[0], - (ps->actions[0] & CURL_POLL_IN) ? "IN" : "", - (ps->actions[0] & CURL_POLL_OUT) ? "OUT" : "", - timeout_count); - break; - case 2: - CURL_TRC_M(data, "%s pollset[fd=%" FMT_SOCKET_T " %s%s, " - "fd=%" FMT_SOCKET_T " %s%s], timeouts=%zu", - caller, ps->sockets[0], - (ps->actions[0] & CURL_POLL_IN) ? "IN" : "", - (ps->actions[0] & CURL_POLL_OUT) ? "OUT" : "", - ps->sockets[1], - (ps->actions[1] & CURL_POLL_IN) ? "IN" : "", - (ps->actions[1] & CURL_POLL_OUT) ? "OUT" : "", - timeout_count); - break; - default: - CURL_TRC_M(data, "%s pollset[fds=%u], timeouts=%zu", - caller, ps->n, timeout_count); - break; + case 0: + CURL_TRC_M(data, "pollset[], timeouts=%zu, paused %d/%d (r/w)", + timeout_count, + Curl_xfer_send_is_paused(data), + Curl_xfer_recv_is_paused(data)); + break; + case 1: + CURL_TRC_M(data, "pollset[fd=%" FMT_SOCKET_T " %s%s], timeouts=%zu", + ps->sockets[0], + (ps->actions[0] & CURL_POLL_IN) ? "IN" : "", + (ps->actions[0] & CURL_POLL_OUT) ? "OUT" : "", + timeout_count); + break; + case 2: + CURL_TRC_M(data, "pollset[fd=%" FMT_SOCKET_T " %s%s, " + "fd=%" FMT_SOCKET_T " %s%s], timeouts=%zu", + ps->sockets[0], + (ps->actions[0] & CURL_POLL_IN) ? "IN" : "", + (ps->actions[0] & CURL_POLL_OUT) ? "OUT" : "", + ps->sockets[1], + (ps->actions[1] & CURL_POLL_IN) ? "IN" : "", + (ps->actions[1] & CURL_POLL_OUT) ? "OUT" : "", + timeout_count); + break; + default: + CURL_TRC_M(data, "pollset[fds=%u], timeouts=%zu", ps->n, timeout_count); + break; } CURL_TRC_EASY_TIMERS(data); } #endif - if(expect_sockets && !ps->n && data->multi && - !Curl_uint_bset_contains(&data->multi->dirty, data->mid) && - !Curl_llist_count(&data->state.timeoutlist) && - !Curl_cwriter_is_paused(data) && !Curl_creader_is_paused(data) && - Curl_conn_is_ip_connected(data, FIRSTSOCKET)) { - /* We expected sockets for POLL monitoring, but none are set. - * We are not dirty (and run anyway). - * We are not waiting on any timer. - * None of the READ/WRITE directions are paused. - * We are connected to the server on IP level, at least. */ - infof(data, "WARNING: no socket in pollset or timer, transfer may stall!"); - DEBUGASSERT(0); - } out: return mresult; } @@ -1196,7 +1233,7 @@ CURLMcode curl_multi_fdset(CURLM *m, return CURLM_RECURSIVE_API_CALL; Curl_pollset_init(&ps); - if(Curl_uint_bset_first(&multi->process, &mid)) { + if(Curl_uint32_bset_first(&multi->process, &mid)) { do { struct Curl_easy *data = Curl_multi_get_easy(multi, mid); @@ -1205,7 +1242,7 @@ CURLMcode curl_multi_fdset(CURLM *m, continue; } - Curl_multi_pollset(data, &ps, "curl_multi_fdset"); + Curl_multi_pollset(data, &ps); for(i = 0; i < ps.n; i++) { if(!FDSET_SOCK(ps.sockets[i])) /* pretend it does not exist */ @@ -1224,8 +1261,7 @@ CURLMcode curl_multi_fdset(CURLM *m, if((int)ps.sockets[i] > this_max_fd) this_max_fd = (int)ps.sockets[i]; } - } - while(Curl_uint_bset_next(&multi->process, mid, &mid)); + } while(Curl_uint32_bset_next(&multi->process, mid, &mid)); } Curl_cshutdn_setfds(&multi->cshutdn, multi->admin, @@ -1243,7 +1279,7 @@ CURLMcode curl_multi_waitfds(CURLM *m, unsigned int *fd_count) { struct Curl_waitfds cwfds; - CURLMcode result = CURLM_OK; + CURLMcode mresult = CURLM_OK; struct Curl_multi *multi = m; struct easy_pollset ps; unsigned int need = 0, mid; @@ -1259,31 +1295,29 @@ CURLMcode curl_multi_waitfds(CURLM *m, Curl_pollset_init(&ps); Curl_waitfds_init(&cwfds, ufds, size); - if(Curl_uint_bset_first(&multi->process, &mid)) { + if(Curl_uint32_bset_first(&multi->process, &mid)) { do { struct Curl_easy *data = Curl_multi_get_easy(multi, mid); if(!data) { DEBUGASSERT(0); - Curl_uint_bset_remove(&multi->process, mid); - Curl_uint_bset_remove(&multi->dirty, mid); + Curl_uint32_bset_remove(&multi->process, mid); + Curl_uint32_bset_remove(&multi->dirty, mid); continue; } - Curl_multi_pollset(data, &ps, "curl_multi_waitfds"); + Curl_multi_pollset(data, &ps); need += Curl_waitfds_add_ps(&cwfds, &ps); - } - while(Curl_uint_bset_next(&multi->process, mid, &mid)); + } while(Curl_uint32_bset_next(&multi->process, mid, &mid)); } need += Curl_cshutdn_add_waitfds(&multi->cshutdn, multi->admin, &cwfds); - if(need != cwfds.n && ufds) { - result = CURLM_OUT_OF_MEMORY; - } + if(need != cwfds.n && ufds) + mresult = CURLM_OUT_OF_MEMORY; if(fd_count) *fd_count = need; Curl_pollset_cleanup(&ps); - return result; + return mresult; } #ifdef USE_WINSOCK @@ -1321,8 +1355,8 @@ static CURLMcode multi_wait(struct Curl_multi *multi, struct curl_pollfds cpfds; unsigned int curl_nfds = 0; /* how many pfds are for curl transfers */ struct Curl_easy *data = NULL; - CURLMcode result = CURLM_OK; - unsigned int mid; + CURLMcode mresult = CURLM_OK; + uint32_t mid; #ifdef USE_WINSOCK WSANETWORKEVENTS wsa_events; @@ -1345,26 +1379,25 @@ static CURLMcode multi_wait(struct Curl_multi *multi, Curl_pollfds_init(&cpfds, a_few_on_stack, NUM_POLLS_ON_STACK); /* Add the curl handles to our pollfds first */ - if(Curl_uint_bset_first(&multi->process, &mid)) { + if(Curl_uint32_bset_first(&multi->process, &mid)) { do { data = Curl_multi_get_easy(multi, mid); if(!data) { DEBUGASSERT(0); - Curl_uint_bset_remove(&multi->process, mid); - Curl_uint_bset_remove(&multi->dirty, mid); + Curl_uint32_bset_remove(&multi->process, mid); + Curl_uint32_bset_remove(&multi->dirty, mid); continue; } - Curl_multi_pollset(data, &ps, "multi_wait"); + Curl_multi_pollset(data, &ps); if(Curl_pollfds_add_ps(&cpfds, &ps)) { - result = CURLM_OUT_OF_MEMORY; + mresult = CURLM_OUT_OF_MEMORY; goto out; } - } - while(Curl_uint_bset_next(&multi->process, mid, &mid)); + } while(Curl_uint32_bset_next(&multi->process, mid, &mid)); } if(Curl_cshutdn_add_pollfds(&multi->cshutdn, multi->admin, &cpfds)) { - result = CURLM_OUT_OF_MEMORY; + mresult = CURLM_OUT_OF_MEMORY; goto out; } @@ -1379,7 +1412,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi, if(extra_fds[i].events & CURL_WAIT_POLLOUT) events |= POLLOUT; if(Curl_pollfds_add_sock(&cpfds, extra_fds[i].fd, events)) { - result = CURLM_OUT_OF_MEMORY; + mresult = CURLM_OUT_OF_MEMORY; goto out; } } @@ -1389,16 +1422,16 @@ static CURLMcode multi_wait(struct Curl_multi *multi, for(i = 0; i < cpfds.n; i++) { long mask = 0; if(cpfds.pfds[i].events & POLLIN) - mask |= FD_READ|FD_ACCEPT|FD_CLOSE; + mask |= FD_READ | FD_ACCEPT | FD_CLOSE; if(cpfds.pfds[i].events & POLLPRI) mask |= FD_OOB; if(cpfds.pfds[i].events & POLLOUT) { - mask |= FD_WRITE|FD_CONNECT|FD_CLOSE; + mask |= FD_WRITE | FD_CONNECT | FD_CLOSE; reset_socket_fdwrite(cpfds.pfds[i].fd); } if(mask) { if(WSAEventSelect(cpfds.pfds[i].fd, multi->wsa_event, mask) != 0) { - result = CURLM_OUT_OF_MEMORY; + mresult = CURLM_OUT_OF_MEMORY; goto out; } } @@ -1409,7 +1442,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi, #ifndef USE_WINSOCK if(use_wakeup && multi->wakeup_pair[0] != CURL_SOCKET_BAD) { if(Curl_pollfds_add_sock(&cpfds, multi->wakeup_pair[0], POLLIN)) { - result = CURLM_OUT_OF_MEMORY; + mresult = CURLM_OUT_OF_MEMORY; goto out; } } @@ -1420,7 +1453,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi, * poll. Collecting the sockets may install new timers by protocols * and connection filters. * Use the shorter one of the internal and the caller requested timeout. */ - (void)multi_timeout(multi, &expire_time, &timeout_internal); + multi_timeout(multi, &expire_time, &timeout_internal); if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms)) timeout_ms = (int)timeout_internal; @@ -1442,7 +1475,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi, pollrc = Curl_poll(cpfds.pfds, cpfds.n, timeout_ms); /* wait... */ #endif if(pollrc < 0) { - result = CURLM_UNRECOVERABLE_POLL; + mresult = CURLM_UNRECOVERABLE_POLL; goto out; } @@ -1468,9 +1501,9 @@ static CURLMcode multi_wait(struct Curl_multi *multi, curl_socket_t s = extra_fds[i].fd; wsa_events.lNetworkEvents = 0; if(WSAEnumNetworkEvents(s, NULL, &wsa_events) == 0) { - if(wsa_events.lNetworkEvents & (FD_READ|FD_ACCEPT|FD_CLOSE)) + if(wsa_events.lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) mask |= CURL_WAIT_POLLIN; - if(wsa_events.lNetworkEvents & (FD_WRITE|FD_CONNECT|FD_CLOSE)) + if(wsa_events.lNetworkEvents & (FD_WRITE | FD_CONNECT | FD_CLOSE)) mask |= CURL_WAIT_POLLOUT; if(wsa_events.lNetworkEvents & FD_OOB) mask |= CURL_WAIT_POLLPRI; @@ -1541,7 +1574,8 @@ static CURLMcode multi_wait(struct Curl_multi *multi, long sleep_ms = 0; /* Avoid busy-looping when there is nothing particular to wait for */ - if(!curl_multi_timeout(multi, &sleep_ms) && sleep_ms) { + multi_timeout(multi, &expire_time, &sleep_ms); + if(sleep_ms) { if(sleep_ms > timeout_ms) sleep_ms = timeout_ms; /* when there are no easy handles in the multi, this holds a -1 @@ -1555,7 +1589,7 @@ static CURLMcode multi_wait(struct Curl_multi *multi, out: Curl_pollset_cleanup(&ps); Curl_pollfds_cleanup(&cpfds); - return result; + return mresult; } CURLMcode curl_multi_wait(CURLM *multi, @@ -1574,8 +1608,7 @@ CURLMcode curl_multi_poll(CURLM *multi, int timeout_ms, int *ret) { - return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, TRUE, - TRUE); + return multi_wait(multi, extra_fds, extra_nfds, timeout_ms, ret, TRUE, TRUE); } CURLMcode curl_multi_wakeup(CURLM *m) @@ -1668,13 +1701,13 @@ CURLMcode Curl_multi_add_perform(struct Curl_multi *multi, struct Curl_easy *data, struct connectdata *conn) { - CURLMcode rc; + CURLMcode mresult; if(multi->in_callback) return CURLM_RECURSIVE_API_CALL; - rc = curl_multi_add_handle(multi, data); - if(!rc) { + mresult = curl_multi_add_handle(multi, data); + if(!mresult) { struct SingleRequest *k = &data->req; CURLcode result; @@ -1691,7 +1724,7 @@ CURLMcode Curl_multi_add_perform(struct Curl_multi *multi, Curl_attach_connection(data, conn); k->keepon |= KEEP_RECV; /* setup to receive! */ } - return rc; + return mresult; } static CURLcode multi_do(struct Curl_easy *data, bool *done) @@ -1734,12 +1767,13 @@ static CURLcode multi_do_more(struct Curl_easy *data, int *complete) * Check whether a timeout occurred, and handle it if it did */ static bool multi_handle_timeout(struct Curl_easy *data, - struct curltime *now, bool *stream_error, CURLcode *result) { bool connect_timeout = data->mstate < MSTATE_DO; - timediff_t timeout_ms = Curl_timeleft(data, now, connect_timeout); + timediff_t timeout_ms; + + timeout_ms = Curl_timeleft_ms(data, connect_timeout); if(timeout_ms < 0) { /* Handle timed out */ struct curltime since; @@ -1749,22 +1783,26 @@ static bool multi_handle_timeout(struct Curl_easy *data, since = data->progress.t_startop; if(data->mstate == MSTATE_RESOLVING) failf(data, "Resolving timed out after %" FMT_TIMEDIFF_T - " milliseconds", curlx_timediff(*now, since)); + " milliseconds", + curlx_ptimediff_ms(Curl_pgrs_now(data), &since)); else if(data->mstate == MSTATE_CONNECTING) failf(data, "Connection timed out after %" FMT_TIMEDIFF_T - " milliseconds", curlx_timediff(*now, since)); + " milliseconds", + curlx_ptimediff_ms(Curl_pgrs_now(data), &since)); else { struct SingleRequest *k = &data->req; if(k->size != -1) { failf(data, "Operation timed out after %" FMT_TIMEDIFF_T " milliseconds with %" FMT_OFF_T " out of %" FMT_OFF_T " bytes received", - curlx_timediff(*now, since), k->bytecount, k->size); + curlx_ptimediff_ms(Curl_pgrs_now(data), &since), + k->bytecount, k->size); } else { failf(data, "Operation timed out after %" FMT_TIMEDIFF_T " milliseconds with %" FMT_OFF_T " bytes received", - curlx_timediff(*now, since), k->bytecount); + curlx_ptimediff_ms(Curl_pgrs_now(data), &since), + k->bytecount); } } *result = CURLE_OPERATION_TIMEDOUT; @@ -1828,47 +1866,31 @@ static CURLcode protocol_doing(struct Curl_easy *data, bool *done) * proceed with some action. * */ -static CURLcode protocol_connect(struct Curl_easy *data, - bool *protocol_done) +static CURLcode protocol_connect(struct Curl_easy *data, bool *protocol_done) { - CURLcode result = CURLE_OK; struct connectdata *conn = data->conn; + CURLcode result = CURLE_OK; + DEBUGASSERT(conn); DEBUGASSERT(protocol_done); + DEBUGASSERT(Curl_conn_is_connected(conn, FIRSTSOCKET)); *protocol_done = FALSE; - - if(Curl_conn_is_connected(conn, FIRSTSOCKET) - && conn->bits.protoconnstart) { - /* We already are connected, get back. This may happen when the connect - worked fine in the first call, like when we connect to a local server - or proxy. Note that we do not know if the protocol is actually done. - - Unless this protocol does not have any protocol-connect callback, as - then we know we are done. */ - if(!conn->handler->connecting) - *protocol_done = TRUE; - - return CURLE_OK; - } - if(!conn->bits.protoconnstart) { if(conn->handler->connect_it) { - /* is there a protocol-specific connect() procedure? */ - /* Call the protocol-specific connect function */ result = conn->handler->connect_it(data, protocol_done); + if(result) + return result; } - else - *protocol_done = TRUE; - - /* it has started, possibly even completed but that knowledge is not stored - in this bit! */ - if(!result) - conn->bits.protoconnstart = TRUE; + conn->bits.protoconnstart = TRUE; } - return result; /* pass back status */ + /* Unless this protocol does not have any protocol-connect callback, as + then we know we are done. */ + if(!conn->handler->connecting) + *protocol_done = TRUE; + return CURLE_OK; } static void set_in_callback(struct Curl_multi *multi, bool value) @@ -1906,56 +1928,48 @@ static CURLcode multi_follow(struct Curl_easy *data, return CURLE_TOO_MANY_REDIRECTS; } -static CURLcode mspeed_check(struct Curl_easy *data, - struct curltime *nowp) +static CURLcode mspeed_check(struct Curl_easy *data) { + const struct curltime *pnow = Curl_pgrs_now(data); timediff_t recv_wait_ms = 0; timediff_t send_wait_ms = 0; - /* check if over send speed */ - if(data->set.max_send_speed) - send_wait_ms = Curl_pgrsLimitWaitTime(&data->progress.ul, - data->set.max_send_speed, - *nowp); - - /* check if over recv speed */ - if(data->set.max_recv_speed) - recv_wait_ms = Curl_pgrsLimitWaitTime(&data->progress.dl, - data->set.max_recv_speed, - *nowp); + /* check if our send/recv limits require idle waits */ + send_wait_ms = Curl_rlimit_wait_ms(&data->progress.ul.rlimit, pnow); + recv_wait_ms = Curl_rlimit_wait_ms(&data->progress.dl.rlimit, pnow); if(send_wait_ms || recv_wait_ms) { if(data->mstate != MSTATE_RATELIMITING) { - Curl_ratelimit(data, *nowp); multistate(data, MSTATE_RATELIMITING); } Curl_expire(data, CURLMAX(send_wait_ms, recv_wait_ms), EXPIRE_TOOFAST); Curl_multi_clear_dirty(data); + CURL_TRC_M(data, "[RLIMIT] waiting %" FMT_TIMEDIFF_T "ms", + CURLMAX(send_wait_ms, recv_wait_ms)); return CURLE_AGAIN; } else if(data->mstate != MSTATE_PERFORMING) { + CURL_TRC_M(data, "[RLIMIT] wait over, continue"); multistate(data, MSTATE_PERFORMING); - Curl_ratelimit(data, *nowp); } return CURLE_OK; } static CURLMcode state_performing(struct Curl_easy *data, - struct curltime *nowp, bool *stream_errorp, CURLcode *resultp) { char *newurl = NULL; bool retry = FALSE; - CURLMcode rc = CURLM_OK; + CURLMcode mresult = CURLM_OK; CURLcode result = *resultp = CURLE_OK; *stream_errorp = FALSE; - if(mspeed_check(data, nowp) == CURLE_AGAIN) + if(mspeed_check(data) == CURLE_AGAIN) return CURLM_OK; /* read/write data if it is ready to do so */ - result = Curl_sendrecv(data, nowp); + result = Curl_sendrecv(data); if(data->req.done || (result == CURLE_RECV_ERROR)) { /* If CURLE_RECV_ERROR happens early enough, we assume it was a race @@ -1989,12 +2003,17 @@ static CURLMcode state_performing(struct Curl_easy *data, data->state.errorbuf = FALSE; if(!newurl) /* typically for HTTP_1_1_REQUIRED error on first flight */ - newurl = strdup(data->state.url); - /* if we are to retry, set the result to OK and consider the request - as done */ - retry = TRUE; - result = CURLE_OK; - data->req.done = TRUE; + newurl = Curl_bufref_dup(&data->state.url); + if(!newurl) { + result = CURLE_OUT_OF_MEMORY; + } + else { + /* if we are to retry, set the result to OK and consider the request + as done */ + retry = TRUE; + result = CURLE_OK; + data->req.done = TRUE; + } } else result = ret; @@ -2030,7 +2049,7 @@ static CURLMcode state_performing(struct Curl_easy *data, if(!retry) { /* if the URL is a follow-location and not just a retried request then figure out the URL here */ - free(newurl); + curlx_free(newurl); newurl = data->req.newurl; data->req.newurl = NULL; follow = FOLLOW_REDIR; @@ -2042,7 +2061,7 @@ static CURLMcode state_performing(struct Curl_easy *data, result = multi_follow(data, handler, newurl, follow); if(!result) { multistate(data, MSTATE_SETUP); - rc = CURLM_CALL_MULTI_PERFORM; + mresult = CURLM_CALL_MULTI_PERFORM; } } else { @@ -2051,7 +2070,7 @@ static CURLMcode state_performing(struct Curl_easy *data, /* but first check to see if we got a location info even though we are not following redirects */ if(data->req.location) { - free(newurl); + curlx_free(newurl); newurl = data->req.location; data->req.location = NULL; result = multi_follow(data, handler, newurl, FOLLOW_FAKE); @@ -2063,23 +2082,23 @@ static CURLMcode state_performing(struct Curl_easy *data, if(!result) { multistate(data, MSTATE_DONE); - rc = CURLM_CALL_MULTI_PERFORM; + mresult = CURLM_CALL_MULTI_PERFORM; } } } else { /* not errored, not done */ - mspeed_check(data, nowp); + mspeed_check(data); } - free(newurl); + curlx_free(newurl); *resultp = result; - return rc; + return mresult; } static CURLMcode state_do(struct Curl_easy *data, bool *stream_errorp, CURLcode *resultp) { - CURLMcode rc = CURLM_OK; + CURLMcode mresult = CURLM_OK; CURLcode result = CURLE_OK; if(data->set.fprereq) { int prereq_rc; @@ -2104,10 +2123,8 @@ static CURLMcode state_do(struct Curl_easy *data, } if(data->set.connect_only && !data->set.connect_only_ws) { - /* keep connection open for application to use the socket */ - connkeep(data->conn, "CONNECT_ONLY"); multistate(data, MSTATE_DONE); - rc = CURLM_CALL_MULTI_PERFORM; + mresult = CURLM_CALL_MULTI_PERFORM; } else { bool dophase_done = FALSE; @@ -2127,9 +2144,8 @@ static CURLMcode state_do(struct Curl_easy *data, multi_done(data, CURLE_OK, FALSE); /* if there is no connection left, skip the DONE state */ - multistate(data, data->conn ? - MSTATE_DONE : MSTATE_COMPLETED); - rc = CURLM_CALL_MULTI_PERFORM; + multistate(data, data->conn ? MSTATE_DONE : MSTATE_COMPLETED); + mresult = CURLM_CALL_MULTI_PERFORM; goto end; } } @@ -2137,7 +2153,7 @@ static CURLMcode state_do(struct Curl_easy *data, /* DO was not completed in one function call, we must continue DOING... */ multistate(data, MSTATE_DOING); - rc = CURLM_CALL_MULTI_PERFORM; + mresult = CURLM_CALL_MULTI_PERFORM; } /* after DO, go DO_DONE... or DO_MORE */ @@ -2145,12 +2161,12 @@ static CURLMcode state_do(struct Curl_easy *data, /* we are supposed to do more, but we need to sit down, relax and wait a little while first */ multistate(data, MSTATE_DOING_MORE); - rc = CURLM_CALL_MULTI_PERFORM; + mresult = CURLM_CALL_MULTI_PERFORM; } else { /* we are done with the DO, now DID */ multistate(data, MSTATE_DID); - rc = CURLM_CALL_MULTI_PERFORM; + mresult = CURLM_CALL_MULTI_PERFORM; } } else if((CURLE_SEND_ERROR == result) && @@ -2183,7 +2199,7 @@ static CURLMcode state_do(struct Curl_easy *data, drc = multi_follow(data, handler, newurl, follow); if(!drc) { multistate(data, MSTATE_SETUP); - rc = CURLM_CALL_MULTI_PERFORM; + mresult = CURLM_CALL_MULTI_PERFORM; result = CURLE_OK; } else { @@ -2200,7 +2216,7 @@ static CURLMcode state_do(struct Curl_easy *data, /* Have error handler disconnect conn if we cannot retry */ *stream_errorp = TRUE; } - free(newurl); + curlx_free(newurl); } else { /* failure detected */ @@ -2212,21 +2228,17 @@ static CURLMcode state_do(struct Curl_easy *data, } end: *resultp = result; - return rc; + return mresult; } static CURLMcode state_ratelimiting(struct Curl_easy *data, - struct curltime *nowp, CURLcode *resultp) { CURLcode result = CURLE_OK; - CURLMcode rc = CURLM_OK; + CURLMcode mresult = CURLM_OK; DEBUGASSERT(data->conn); /* if both rates are within spec, resume transfer */ - if(Curl_pgrsUpdate(data)) - result = CURLE_ABORTED_BY_CALLBACK; - else - result = Curl_speedcheck(data, *nowp); + result = Curl_pgrsCheck(data); if(result) { if(!(data->conn->handler->flags & PROTOPT_DUAL) && @@ -2237,11 +2249,11 @@ static CURLMcode state_ratelimiting(struct Curl_easy *data, multi_done(data, result, TRUE); } else { - if(!mspeed_check(data, nowp)) - rc = CURLM_CALL_MULTI_PERFORM; + if(!mspeed_check(data)) + mresult = CURLM_CALL_MULTI_PERFORM; } *resultp = result; - return rc; + return mresult; } static CURLMcode state_resolving(struct Curl_multi *multi, @@ -2251,7 +2263,7 @@ static CURLMcode state_resolving(struct Curl_multi *multi, { struct Curl_dns_entry *dns = NULL; CURLcode result; - CURLMcode rc = CURLM_OK; + CURLMcode mresult = CURLM_OK; result = Curl_resolv_check(data, &dns); CURL_TRC_DNS(data, "Curl_resolv_check() -> %d, %s", @@ -2261,9 +2273,9 @@ static CURLMcode state_resolving(struct Curl_multi *multi, socket(s) will again be used further down. If the name has not yet been resolved, it is likely that new sockets have been opened in an attempt to contact another resolver. */ - rc = Curl_multi_ev_assess_xfer(multi, data); - if(rc) - return rc; + mresult = Curl_multi_ev_assess_xfer(multi, data); + if(mresult) + return mresult; if(dns) { bool connected; @@ -2277,7 +2289,7 @@ static CURLMcode state_resolving(struct Curl_multi *multi, data->conn = NULL; /* no more connection */ else { /* call again please so that we get the next socket setup */ - rc = CURLM_CALL_MULTI_PERFORM; + mresult = CURLM_CALL_MULTI_PERFORM; if(connected) multistate(data, MSTATE_PROTOCONNECT); else { @@ -2291,36 +2303,34 @@ static CURLMcode state_resolving(struct Curl_multi *multi, *stream_errorp = TRUE; *resultp = result; - return rc; + return mresult; } static CURLMcode state_connect(struct Curl_multi *multi, struct Curl_easy *data, - struct curltime *nowp, CURLcode *resultp) { /* Connect. We want to get a connection identifier filled in. This state can be entered from SETUP and from PENDING. */ bool connected; bool async; - CURLMcode rc = CURLM_OK; + CURLMcode mresult = CURLM_OK; CURLcode result = Curl_connect(data, &async, &connected); if(CURLE_NO_CONNECTION_AVAILABLE == result) { /* There was no connection available. We will go to the pending state and wait for an available connection. */ multistate(data, MSTATE_PENDING); /* move from process to pending set */ - Curl_uint_bset_remove(&multi->process, data->mid); - Curl_uint_bset_remove(&multi->dirty, data->mid); - Curl_uint_bset_add(&multi->pending, data->mid); + Curl_uint32_bset_remove(&multi->process, data->mid); + Curl_uint32_bset_remove(&multi->dirty, data->mid); + Curl_uint32_bset_add(&multi->pending, data->mid); *resultp = CURLE_OK; - return rc; + return mresult; } else process_pending_handles(data->multi); if(!result) { - *nowp = Curl_pgrsTime(data, TIMER_POSTQUEUE); if(async) /* We are now waiting for an asynchronous name lookup */ multistate(data, MSTATE_RESOLVING); @@ -2328,7 +2338,7 @@ static CURLMcode state_connect(struct Curl_multi *multi, /* after the connect has been sent off, go WAITCONNECT unless the protocol connect is already done and we can go directly to WAITDO or DO! */ - rc = CURLM_CALL_MULTI_PERFORM; + mresult = CURLM_CALL_MULTI_PERFORM; if(connected) { if(!data->conn->bits.reuse && @@ -2344,18 +2354,17 @@ static CURLMcode state_connect(struct Curl_multi *multi, } } *resultp = result; - return rc; + return mresult; } static CURLMcode multi_runsingle(struct Curl_multi *multi, - struct curltime *nowp, struct Curl_easy *data) { struct Curl_message *msg = NULL; bool connected; bool protocol_connected = FALSE; bool dophase_done = FALSE; - CURLMcode rc; + CURLMcode mresult; CURLcode result = CURLE_OK; int control; @@ -2375,13 +2384,18 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, /* transfer runs now, clear the dirty bit. This may be set * again during processing, triggering a re-run later. */ - Curl_uint_bset_remove(&multi->dirty, data->mid); + Curl_uint32_bset_remove(&multi->dirty, data->mid); + + if(data == multi->admin) { + Curl_cshutdn_perform(&multi->cshutdn, multi->admin, CURL_SOCKET_TIMEOUT); + return CURLM_OK; + } do { /* A "stream" here is a logical stream if the protocol can handle that (HTTP/2), or the full connection for older protocols */ bool stream_error = FALSE; - rc = CURLM_OK; + mresult = CURLM_OK; if(multi_ischanged(multi, TRUE)) { CURL_TRC_M(data, "multi changed, check CONNECT_PEND queue"); @@ -2399,7 +2413,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, /* Wait for the connect state as only then is the start time stored, but we must not check already completed handles */ if((data->mstate >= MSTATE_CONNECT) && (data->mstate < MSTATE_COMPLETED) && - multi_handle_timeout(data, nowp, &stream_error, &result)) + multi_handle_timeout(data, &stream_error, &result)) /* Skip the statemachine and go directly to error handling section. */ goto statemachine_end; @@ -2419,7 +2433,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, case MSTATE_SETUP: /* Transitional state. Setup things for a new transfer. The handle can come back to this state on a redirect. */ - *nowp = Curl_pgrsTime(data, TIMER_STARTSINGLE); + Curl_pgrsTime(data, TIMER_STARTSINGLE); if(data->set.timeout) Curl_expire(data, data->set.timeout, EXPIRE_TIMEOUT); if(data->set.connecttimeout) @@ -2432,28 +2446,13 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, FALLTHROUGH(); case MSTATE_CONNECT: - rc = state_connect(multi, data, nowp, &result); + mresult = state_connect(multi, data, &result); break; case MSTATE_RESOLVING: /* awaiting an asynch name resolve to complete */ - rc = state_resolving(multi, data, &stream_error, &result); - break; - -#ifndef CURL_DISABLE_HTTP - case MSTATE_TUNNELING: - /* this is HTTP-specific, but sending CONNECT to a proxy is HTTP... */ - DEBUGASSERT(data->conn); - result = Curl_http_connect(data, &protocol_connected); - if(!result) { - rc = CURLM_CALL_MULTI_PERFORM; - /* initiate protocol connect phase */ - multistate(data, MSTATE_PROTOCONNECT); - } - else - stream_error = TRUE; + mresult = state_resolving(multi, data, &stream_error, &result); break; -#endif case MSTATE_CONNECTING: /* awaiting a completion of an asynch TCP connect */ @@ -2466,7 +2465,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, /* new connection, can multiplex, wake pending handles */ process_pending_handles(data->multi); } - rc = CURLM_CALL_MULTI_PERFORM; + mresult = CURLM_CALL_MULTI_PERFORM; multistate(data, MSTATE_PROTOCONNECT); } else if(result) { @@ -2486,7 +2485,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, * restart this on a reused connection. */ multistate(data, MSTATE_DO); - rc = CURLM_CALL_MULTI_PERFORM; + mresult = CURLM_CALL_MULTI_PERFORM; break; } if(!result) @@ -2494,12 +2493,12 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, if(!result && !protocol_connected) { /* switch to waiting state */ multistate(data, MSTATE_PROTOCONNECTING); - rc = CURLM_CALL_MULTI_PERFORM; + mresult = CURLM_CALL_MULTI_PERFORM; } else if(!result) { /* protocol connect has completed, go WAITDO or DO */ multistate(data, MSTATE_DO); - rc = CURLM_CALL_MULTI_PERFORM; + mresult = CURLM_CALL_MULTI_PERFORM; } else { /* failure detected */ @@ -2515,7 +2514,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, if(!result && protocol_connected) { /* after the connect has completed, go WAITDO or DO */ multistate(data, MSTATE_DO); - rc = CURLM_CALL_MULTI_PERFORM; + mresult = CURLM_CALL_MULTI_PERFORM; } else if(result) { /* failure detected */ @@ -2526,7 +2525,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, break; case MSTATE_DO: - rc = state_do(data, &stream_error, &result); + mresult = state_do(data, &stream_error, &result); break; case MSTATE_DOING: @@ -2538,7 +2537,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, /* after DO, go DO_DONE or DO_MORE */ multistate(data, data->conn->bits.do_more ? MSTATE_DOING_MORE : MSTATE_DID); - rc = CURLM_CALL_MULTI_PERFORM; + mresult = CURLM_CALL_MULTI_PERFORM; } /* dophase_done */ } else { @@ -2560,9 +2559,8 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, if(control) { /* if positive, advance to DO_DONE if negative, go back to DOING */ - multistate(data, control == 1 ? - MSTATE_DID : MSTATE_DOING); - rc = CURLM_CALL_MULTI_PERFORM; + multistate(data, control == 1 ? MSTATE_DID : MSTATE_DOING); + mresult = CURLM_CALL_MULTI_PERFORM; } /* else stay in DO_MORE */ @@ -2579,7 +2577,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, DEBUGASSERT(data->conn); if(data->conn->bits.multiplex) /* Check if we can move pending requests to send pipe */ - process_pending_handles(multi); /* multiplexed */ + process_pending_handles(multi); /* multiplexed */ /* Only perform the transfer if there is a good socket to work with. Having both BAD is a signal to skip immediately to DONE */ @@ -2595,20 +2593,20 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, #endif multistate(data, MSTATE_DONE); } - rc = CURLM_CALL_MULTI_PERFORM; + mresult = CURLM_CALL_MULTI_PERFORM; break; case MSTATE_RATELIMITING: /* limit-rate exceeded in either direction */ - rc = state_ratelimiting(data, nowp, &result); + mresult = state_ratelimiting(data, &result); break; case MSTATE_PERFORMING: - rc = state_performing(data, nowp, &stream_error, &result); + mresult = state_performing(data, &stream_error, &result); break; case MSTATE_DONE: /* this state is highly transient, so run another loop after this */ - rc = CURLM_CALL_MULTI_PERFORM; + mresult = CURLM_CALL_MULTI_PERFORM; if(data->conn) { CURLcode res; @@ -2650,7 +2648,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, if(data->mstate >= MSTATE_CONNECT && data->mstate < MSTATE_DO && - rc != CURLM_CALL_MULTI_PERFORM && + mresult != CURLM_CALL_MULTI_PERFORM && !multi_ischanged(multi, FALSE)) { /* We now handle stream timeouts if and only if this will be the last * loop iteration. We only check this on the last iteration to ensure @@ -2658,7 +2656,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, * (i.e. CURLM_CALL_MULTI_PERFORM == TRUE) then we should do that before * declaring the connection timed out as we may almost have a completed * connection. */ - multi_handle_timeout(data, nowp, &stream_error, &result); + multi_handle_timeout(data, &stream_error, &result); } statemachine_end: @@ -2696,24 +2694,26 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, } multistate(data, MSTATE_COMPLETED); - rc = CURLM_CALL_MULTI_PERFORM; + mresult = CURLM_CALL_MULTI_PERFORM; } /* if there is still a connection to use, call the progress function */ - else if(data->conn && Curl_pgrsUpdate(data)) { - /* aborted due to progress callback return code must close the - connection */ - result = CURLE_ABORTED_BY_CALLBACK; - streamclose(data->conn, "Aborted by callback"); - - /* if not yet in DONE state, go there, otherwise COMPLETED */ - multistate(data, (data->mstate < MSTATE_DONE) ? - MSTATE_DONE : MSTATE_COMPLETED); - rc = CURLM_CALL_MULTI_PERFORM; + else if(data->conn) { + result = Curl_pgrsUpdate(data); + if(result) { + /* aborted due to progress callback return code must close the + connection */ + streamclose(data->conn, "Aborted by callback"); + + /* if not yet in DONE state, go there, otherwise COMPLETED */ + multistate(data, (data->mstate < MSTATE_DONE) ? + MSTATE_DONE : MSTATE_COMPLETED); + mresult = CURLM_CALL_MULTI_PERFORM; + } } } if(MSTATE_COMPLETED == data->mstate) { - if(data->master_mid != UINT_MAX) { + if(data->master_mid != UINT32_MAX) { /* A sub transfer, not for msgsent to application */ struct Curl_easy *mdata; @@ -2744,32 +2744,28 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, multistate(data, MSTATE_MSGSENT); /* remove from the other sets, add to msgsent */ - Curl_uint_bset_remove(&multi->process, data->mid); - Curl_uint_bset_remove(&multi->dirty, data->mid); - Curl_uint_bset_remove(&multi->pending, data->mid); - Curl_uint_bset_add(&multi->msgsent, data->mid); + Curl_uint32_bset_remove(&multi->process, data->mid); + Curl_uint32_bset_remove(&multi->dirty, data->mid); + Curl_uint32_bset_remove(&multi->pending, data->mid); + Curl_uint32_bset_add(&multi->msgsent, data->mid); --multi->xfers_alive; return CURLM_OK; } - } while((rc == CURLM_CALL_MULTI_PERFORM) || multi_ischanged(multi, FALSE)); + } while((mresult == CURLM_CALL_MULTI_PERFORM) || + multi_ischanged(multi, FALSE)); data->result = result; - return rc; + return mresult; } - -CURLMcode curl_multi_perform(CURLM *m, int *running_handles) +static CURLMcode multi_perform(struct Curl_multi *multi, + int *running_handles) { CURLMcode returncode = CURLM_OK; - struct Curl_tree *t = NULL; - struct curltime now = curlx_now(); - struct Curl_multi *multi = m; - unsigned int mid; + struct curltime start = *multi_now(multi); + uint32_t mid; SIGPIPE_VARIABLE(pipe_st); - if(!GOOD_MULTI_HANDLE(multi)) - return CURLM_BAD_HANDLE; - if(multi->in_callback) return CURLM_RECURSIVE_API_CALL; @@ -2777,37 +2773,30 @@ CURLMcode curl_multi_perform(CURLM *m, int *running_handles) return CURLM_RECURSIVE_API_CALL; sigpipe_init(&pipe_st); - if(Curl_uint_bset_first(&multi->process, &mid)) { + if(Curl_uint32_bset_first(&multi->process, &mid)) { CURL_TRC_M(multi->admin, "multi_perform(running=%u)", Curl_multi_xfers_running(multi)); do { struct Curl_easy *data = Curl_multi_get_easy(multi, mid); - CURLMcode result; + CURLMcode mresult; if(!data) { DEBUGASSERT(0); - Curl_uint_bset_remove(&multi->process, mid); - Curl_uint_bset_remove(&multi->dirty, mid); + Curl_uint32_bset_remove(&multi->process, mid); + Curl_uint32_bset_remove(&multi->dirty, mid); continue; } - if(data != multi->admin) { - /* admin handle is processed below */ - sigpipe_apply(data, &pipe_st); - result = multi_runsingle(multi, &now, data); - if(result) - returncode = result; - } - } - while(Curl_uint_bset_next(&multi->process, mid, &mid)); + sigpipe_apply(data, &pipe_st); + mresult = multi_runsingle(multi, data); + if(mresult) + returncode = mresult; + } while(Curl_uint32_bset_next(&multi->process, mid, &mid)); } - - sigpipe_apply(multi->admin, &pipe_st); - Curl_cshutdn_perform(&multi->cshutdn, multi->admin, CURL_SOCKET_TIMEOUT); sigpipe_restore(&pipe_st); - if(multi_ischanged(m, TRUE)) - process_pending_handles(m); + if(multi_ischanged(multi, TRUE)) + process_pending_handles(multi); - if(!returncode) + if(!returncode && CURL_MNTFY_HAS_ENTRIES(multi)) returncode = Curl_mntfy_dispatch_all(multi); /* @@ -2820,22 +2809,25 @@ CURLMcode curl_multi_perform(CURLM *m, int *running_handles) * then and then we risk this loop to remove timers that actually have not * been handled! */ - do { - multi->timetree = Curl_splaygetbest(now, multi->timetree, &t); - if(t) { - /* the removed may have another timeout in queue */ - struct Curl_easy *data = Curl_splayget(t); - (void)add_next_timeout(now, multi, data); - if(data->mstate == MSTATE_PENDING) { - bool stream_unused; - CURLcode result_unused; - if(multi_handle_timeout(data, &now, &stream_unused, &result_unused)) { - infof(data, "PENDING handle timeout"); - move_pending_to_connect(multi, data); + if(multi->timetree) { + struct Curl_tree *t = NULL; + do { + multi->timetree = Curl_splaygetbest(&start, multi->timetree, &t); + if(t) { + /* the removed may have another timeout in queue */ + struct Curl_easy *data = Curl_splayget(t); + (void)add_next_timeout(&start, multi, data); + if(data->mstate == MSTATE_PENDING) { + bool stream_unused; + CURLcode result_unused; + if(multi_handle_timeout(data, &stream_unused, &result_unused)) { + infof(data, "PENDING handle timeout"); + move_pending_to_connect(multi, data); + } } } - } - } while(t); + } while(t); + } if(running_handles) { unsigned int running = Curl_multi_xfers_running(multi); @@ -2848,12 +2840,22 @@ CURLMcode curl_multi_perform(CURLM *m, int *running_handles) return returncode; } +CURLMcode curl_multi_perform(CURLM *m, int *running_handles) +{ + struct Curl_multi *multi = m; + + if(!GOOD_MULTI_HANDLE(multi)) + return CURLM_BAD_HANDLE; + + return multi_perform(multi, running_handles); +} + CURLMcode curl_multi_cleanup(CURLM *m) { struct Curl_multi *multi = m; if(GOOD_MULTI_HANDLE(multi)) { void *entry; - unsigned int mid; + uint32_t mid; if(multi->in_callback) return CURLM_RECURSIVE_API_CALL; if(multi->in_ntfy_callback) @@ -2861,7 +2863,7 @@ CURLMcode curl_multi_cleanup(CURLM *m) /* First remove all remaining easy handles, * close internal ones. admin handle is special */ - if(Curl_uint_tbl_first(&multi->xfers, &mid, &entry)) { + if(Curl_uint32_tbl_first(&multi->xfers, &mid, &entry)) { do { struct Curl_easy *data = entry; if(!GOOD_EASY_HANDLE(data)) @@ -2883,8 +2885,8 @@ CURLMcode curl_multi_cleanup(CURLM *m) (void)multi_done(data, CURLE_OK, TRUE); data->multi = NULL; /* clear the association */ - Curl_uint_tbl_remove(&multi->xfers, mid); - data->mid = UINT_MAX; + Curl_uint32_tbl_remove(&multi->xfers, mid); + data->mid = UINT32_MAX; #ifdef USE_LIBPSL if(data->psl == &multi->psl) @@ -2892,8 +2894,7 @@ CURLMcode curl_multi_cleanup(CURLM *m) #endif if(data->state.internal) Curl_close(&data); - } - while(Curl_uint_tbl_next(&multi->xfers, mid, &mid, &entry)); + } while(Curl_uint32_tbl_next(&multi->xfers, mid, &mid, &entry)); } Curl_cpool_destroy(&multi->cpool); @@ -2901,7 +2902,7 @@ CURLMcode curl_multi_cleanup(CURLM *m) if(multi->admin) { CURL_TRC_M(multi->admin, "multi_cleanup, closing admin handle, done"); multi->admin->multi = NULL; - Curl_uint_tbl_remove(&multi->xfers, multi->admin->mid); + Curl_uint32_tbl_remove(&multi->xfers, multi->admin->mid); Curl_close(&multi->admin); } @@ -2929,17 +2930,17 @@ CURLMcode curl_multi_cleanup(CURLM *m) multi_xfer_bufs_free(multi); Curl_mntfy_cleanup(multi); #ifdef DEBUGBUILD - if(Curl_uint_tbl_count(&multi->xfers)) { + if(Curl_uint32_tbl_count(&multi->xfers)) { multi_xfer_tbl_dump(multi); DEBUGASSERT(0); } #endif - Curl_uint_bset_destroy(&multi->process); - Curl_uint_bset_destroy(&multi->dirty); - Curl_uint_bset_destroy(&multi->pending); - Curl_uint_bset_destroy(&multi->msgsent); - Curl_uint_tbl_destroy(&multi->xfers); - free(multi); + Curl_uint32_bset_destroy(&multi->process); + Curl_uint32_bset_destroy(&multi->dirty); + Curl_uint32_bset_destroy(&multi->pending); + Curl_uint32_bset_destroy(&multi->msgsent); + Curl_uint32_tbl_destroy(&multi->xfers); + curlx_free(multi); return CURLM_OK; } @@ -2984,7 +2985,6 @@ CURLMsg *curl_multi_info_read(CURLM *m, int *msgs_in_queue) return NULL; } - void Curl_multi_will_close(struct Curl_easy *data, curl_socket_t s) { if(data) { @@ -3008,7 +3008,7 @@ void Curl_multi_will_close(struct Curl_easy *data, curl_socket_t s) * The splay tree only has each sessionhandle as a single node and the nearest * timeout is used to sort it on. */ -static CURLMcode add_next_timeout(struct curltime now, +static CURLMcode add_next_timeout(const struct curltime *pnow, struct Curl_multi *multi, struct Curl_easy *d) { @@ -3022,7 +3022,7 @@ static CURLMcode add_next_timeout(struct curltime now, for(e = Curl_llist_head(list); e;) { struct Curl_llist_node *n = Curl_node_next(e); struct time_node *node = Curl_node_elem(e); - timediff_t diff = curlx_timediff_us(node->time, now); + timediff_t diff = curlx_ptimediff_us(&node->time, pnow); if(diff <= 0) /* remove outdated entry */ Curl_node_remove(e); @@ -3045,7 +3045,7 @@ static CURLMcode add_next_timeout(struct curltime now, /* Insert this node again into the splay. Keep the timer in the list in case we need to recompute future timers. */ - multi->timetree = Curl_splayinsert(*tv, multi->timetree, + multi->timetree = Curl_splayinsert(tv, multi->timetree, &d->state.timenode); } return CURLM_OK; @@ -3053,13 +3053,12 @@ static CURLMcode add_next_timeout(struct curltime now, struct multi_run_ctx { struct Curl_multi *multi; - struct curltime now; size_t run_xfers; SIGPIPE_MEMBER(pipe_st); - bool run_cpool; }; -static void multi_mark_expired_as_dirty(struct multi_run_ctx *mrc) +static void multi_mark_expired_as_dirty(struct multi_run_ctx *mrc, + const struct curltime *ts) { struct Curl_multi *multi = mrc->multi; struct Curl_easy *data = NULL; @@ -3073,7 +3072,7 @@ static void multi_mark_expired_as_dirty(struct multi_run_ctx *mrc) while(1) { /* Check if there is one (more) expired timer to deal with! This function extracts a matching node if there is one */ - multi->timetree = Curl_splaygetbest(mrc->now, multi->timetree, &t); + multi->timetree = Curl_splaygetbest(ts, multi->timetree, &t); if(!t) return; @@ -3089,7 +3088,7 @@ static void multi_mark_expired_as_dirty(struct multi_run_ctx *mrc) } } #endif - (void)add_next_timeout(mrc->now, multi, data); + (void)add_next_timeout(ts, multi, data); Curl_multi_mark_dirty(data); } } @@ -3097,48 +3096,42 @@ static void multi_mark_expired_as_dirty(struct multi_run_ctx *mrc) static CURLMcode multi_run_dirty(struct multi_run_ctx *mrc) { struct Curl_multi *multi = mrc->multi; - CURLMcode result = CURLM_OK; - unsigned int mid; + CURLMcode mresult = CURLM_OK; + uint32_t mid; - if(Curl_uint_bset_first(&multi->dirty, &mid)) { + if(Curl_uint32_bset_first(&multi->dirty, &mid)) { do { struct Curl_easy *data = Curl_multi_get_easy(multi, mid); if(data) { CURL_TRC_M(data, "multi_run_dirty"); - if(data == multi->admin) { - Curl_uint_bset_remove(&multi->dirty, mid); - mrc->run_cpool = TRUE; - continue; - } - else if(!Curl_uint_bset_contains(&multi->process, mid)) { + if(!Curl_uint32_bset_contains(&multi->process, mid)) { /* We are no longer processing this transfer */ - Curl_uint_bset_remove(&multi->dirty, mid); + Curl_uint32_bset_remove(&multi->dirty, mid); continue; } mrc->run_xfers++; sigpipe_apply(data, &mrc->pipe_st); /* runsingle() clears the dirty mid */ - result = multi_runsingle(multi, &mrc->now, data); + mresult = multi_runsingle(multi, data); - if(CURLM_OK >= result) { + if(CURLM_OK >= mresult) { /* reassess event handling of data */ - result = Curl_multi_ev_assess_xfer(multi, data); - if(result) + mresult = Curl_multi_ev_assess_xfer(multi, data); + if(mresult) goto out; } } else { CURL_TRC_M(multi->admin, "multi_run_dirty, %u no longer found", mid); - Curl_uint_bset_remove(&multi->dirty, mid); + Curl_uint32_bset_remove(&multi->dirty, mid); } - } - while(Curl_uint_bset_next(&multi->dirty, mid, &mid)); + } while(Curl_uint32_bset_next(&multi->dirty, mid, &mid)); } out: - return result; + return mresult; } static CURLMcode multi_socket(struct Curl_multi *multi, @@ -3147,30 +3140,28 @@ static CURLMcode multi_socket(struct Curl_multi *multi, int ev_bitmask, int *running_handles) { - CURLMcode result = CURLM_OK; + CURLMcode mresult = CURLM_OK; struct multi_run_ctx mrc; (void)ev_bitmask; memset(&mrc, 0, sizeof(mrc)); mrc.multi = multi; - mrc.now = curlx_now(); sigpipe_init(&mrc.pipe_st); if(checkall) { /* *perform() deals with running_handles on its own */ - result = curl_multi_perform(multi, running_handles); + mresult = multi_perform(multi, running_handles); - if(result != CURLM_BAD_HANDLE) { + if(mresult != CURLM_BAD_HANDLE) { /* Reassess event status of all active transfers */ - result = Curl_multi_ev_assess_xfer_bset(multi, &multi->process); + mresult = Curl_multi_ev_assess_xfer_bset(multi, &multi->process); } - mrc.run_cpool = TRUE; goto out; } if(s != CURL_SOCKET_TIMEOUT) { /* Mark all transfers of that socket as dirty */ - Curl_multi_ev_dirty_xfers(multi, s, &mrc.run_cpool); + Curl_multi_ev_dirty_xfers(multi, s); } else { /* Asked to run due to time-out. Clear the 'last_expire_ts' variable to @@ -3179,12 +3170,11 @@ static CURLMcode multi_socket(struct Curl_multi *multi, handles the case when the application asks libcurl to run the timeout prematurely. */ memset(&multi->last_expire_ts, 0, sizeof(multi->last_expire_ts)); - mrc.run_cpool = TRUE; } - multi_mark_expired_as_dirty(&mrc); - result = multi_run_dirty(&mrc); - if(result) + multi_mark_expired_as_dirty(&mrc, multi_now(multi)); + mresult = multi_run_dirty(&mrc); + if(mresult) goto out; if(mrc.run_xfers) { @@ -3193,39 +3183,33 @@ static CURLMcode multi_socket(struct Curl_multi *multi, * to set a 0 timeout and call us again, we run them here. * Do that only once or it might be unfair to transfers on other * sockets. */ - mrc.now = curlx_now(); - multi_mark_expired_as_dirty(&mrc); - result = multi_run_dirty(&mrc); + multi_mark_expired_as_dirty(&mrc, &multi->now); + mresult = multi_run_dirty(&mrc); } out: - if(mrc.run_cpool) { - sigpipe_apply(multi->admin, &mrc.pipe_st); - Curl_cshutdn_perform(&multi->cshutdn, multi->admin, s); - } sigpipe_restore(&mrc.pipe_st); if(multi_ischanged(multi, TRUE)) process_pending_handles(multi); - if(!result) - result = Curl_mntfy_dispatch_all(multi); + if(!mresult && CURL_MNTFY_HAS_ENTRIES(multi)) + mresult = Curl_mntfy_dispatch_all(multi); if(running_handles) { unsigned int running = Curl_multi_xfers_running(multi); *running_handles = (running < INT_MAX) ? (int)running : INT_MAX; } - if(CURLM_OK >= result) - result = Curl_update_timer(multi); - return result; + if(CURLM_OK >= mresult) + mresult = Curl_update_timer(multi); + return mresult; } #undef curl_multi_setopt -CURLMcode curl_multi_setopt(CURLM *m, - CURLMoption option, ...) +CURLMcode curl_multi_setopt(CURLM *m, CURLMoption option, ...) { - CURLMcode res = CURLM_OK; + CURLMcode mresult = CURLM_OK; va_list param; unsigned long uarg; struct Curl_multi *multi = m; @@ -3266,10 +3250,12 @@ CURLMcode curl_multi_setopt(CURLM *m, multi->maxconnects = (unsigned int)uarg; break; case CURLMOPT_MAX_HOST_CONNECTIONS: - multi->max_host_connections = va_arg(param, long); + if(!curlx_sltouz(va_arg(param, long), &multi->max_host_connections)) + mresult = CURLM_BAD_FUNCTION_ARGUMENT; break; case CURLMOPT_MAX_TOTAL_CONNECTIONS: - multi->max_total_connections = va_arg(param, long); + if(!curlx_sltouz(va_arg(param, long), &multi->max_total_connections)) + mresult = CURLM_BAD_FUNCTION_ARGUMENT; break; /* options formerly used for pipelining */ case CURLMOPT_MAX_PIPELINE_LENGTH: @@ -3282,14 +3268,13 @@ CURLMcode curl_multi_setopt(CURLM *m, break; case CURLMOPT_PIPELINING_SERVER_BL: break; - case CURLMOPT_MAX_CONCURRENT_STREAMS: - { - long streams = va_arg(param, long); - if((streams < 1) || (streams > INT_MAX)) - streams = 100; - multi->max_concurrent_streams = (unsigned int)streams; - } + case CURLMOPT_MAX_CONCURRENT_STREAMS: { + long streams = va_arg(param, long); + if((streams < 1) || (streams > INT_MAX)) + streams = 100; + multi->max_concurrent_streams = (unsigned int)streams; break; + } case CURLMOPT_NETWORK_CHANGED: { long val = va_arg(param, long); if(val & CURLMNWC_CLEAR_DNS) { @@ -3307,11 +3292,11 @@ CURLMcode curl_multi_setopt(CURLM *m, multi->ntfy.ntfy_cb_data = va_arg(param, void *); break; default: - res = CURLM_UNKNOWN_OPTION; + mresult = CURLM_UNKNOWN_OPTION; break; } va_end(param); - return res; + return mresult; } /* we define curl_multi_socket() in the public multi.h header */ @@ -3348,54 +3333,50 @@ CURLMcode curl_multi_socket_all(CURLM *m, int *running_handles) return multi_socket(multi, TRUE, CURL_SOCKET_BAD, 0, running_handles); } - static bool multi_has_dirties(struct Curl_multi *multi) { - unsigned int mid; - if(Curl_uint_bset_first(&multi->dirty, &mid)) { + uint32_t mid; + if(Curl_uint32_bset_first(&multi->dirty, &mid)) { do { struct Curl_easy *data = Curl_multi_get_easy(multi, mid); if(data) { - if(Curl_uint_bset_contains(&multi->process, mid)) + if(Curl_uint32_bset_contains(&multi->process, mid)) return TRUE; /* We are no longer processing this transfer */ - Curl_uint_bset_remove(&multi->dirty, mid); + Curl_uint32_bset_remove(&multi->dirty, mid); } else { CURL_TRC_M(multi->admin, "dirty transfer %u no longer found", mid); - Curl_uint_bset_remove(&multi->dirty, mid); + Curl_uint32_bset_remove(&multi->dirty, mid); } - } - while(Curl_uint_bset_next(&multi->dirty, mid, &mid)); + } while(Curl_uint32_bset_next(&multi->dirty, mid, &mid)); } return FALSE; } -static CURLMcode multi_timeout(struct Curl_multi *multi, - struct curltime *expire_time, - long *timeout_ms) +static void multi_timeout(struct Curl_multi *multi, + struct curltime *expire_time, + long *timeout_ms) { - static const struct curltime tv_zero = {0, 0}; + static const struct curltime tv_zero = { 0, 0 }; #ifndef CURL_DISABLE_VERBOSE_STRINGS struct Curl_easy *data = NULL; #endif if(multi->dead) { *timeout_ms = 0; - return CURLM_OK; + return; } if(multi_has_dirties(multi)) { - *expire_time = curlx_now(); + *expire_time = *multi_now(multi); *timeout_ms = 0; - return CURLM_OK; + return; } else if(multi->timetree) { - /* we have a tree of expire times */ - struct curltime now = curlx_now(); - + const struct curltime *pnow = multi_now(multi); /* splay the lowest to the bottom */ - multi->timetree = Curl_splay(tv_zero, multi->timetree); + multi->timetree = Curl_splay(&tv_zero, multi->timetree); /* this will not return NULL from a non-empty tree, but some compilers * are not convinced of that. Analyzers are hard. */ *expire_time = multi->timetree ? multi->timetree->key : tv_zero; @@ -3403,15 +3384,16 @@ static CURLMcode multi_timeout(struct Curl_multi *multi, /* 'multi->timetree' will be non-NULL here but the compilers sometimes yell at us if we assume so */ if(multi->timetree && - curlx_timediff_us(multi->timetree->key, now) > 0) { + curlx_ptimediff_us(&multi->timetree->key, pnow) > 0) { /* some time left before expiration */ - timediff_t diff = curlx_timediff_ceil(multi->timetree->key, now); + timediff_t diff_ms = + curlx_timediff_ceil_ms(multi->timetree->key, *pnow); #ifndef CURL_DISABLE_VERBOSE_STRINGS data = Curl_splayget(multi->timetree); #endif /* this should be safe even on 32-bit archs, as we do not use that overly long timeouts */ - *timeout_ms = (long)diff; + *timeout_ms = (long)diff_ms; } else { #ifndef CURL_DISABLE_VERBOSE_STRINGS @@ -3430,8 +3412,7 @@ static CURLMcode multi_timeout(struct Curl_multi *multi, #ifndef CURL_DISABLE_VERBOSE_STRINGS if(data && CURL_TRC_TIMER_is_verbose(data)) { - struct Curl_llist_node *e = - Curl_llist_head(&data->state.timeoutlist); + struct Curl_llist_node *e = Curl_llist_head(&data->state.timeoutlist); if(e) { struct time_node *n = Curl_node_elem(e); CURL_TRC_TIMER(data, n->eid, "gives multi timeout in %ldms", @@ -3439,8 +3420,6 @@ static CURLMcode multi_timeout(struct Curl_multi *multi, } } #endif - - return CURLM_OK; } CURLMcode curl_multi_timeout(CURLM *m, @@ -3456,7 +3435,8 @@ CURLMcode curl_multi_timeout(CURLM *m, if(multi->in_callback) return CURLM_RECURSIVE_API_CALL; - return multi_timeout(multi, &expire_time, timeout_ms); + multi_timeout(multi, &expire_time, timeout_ms); + return CURLM_OK; } /* @@ -3472,9 +3452,7 @@ CURLMcode Curl_update_timer(struct Curl_multi *multi) if(!multi->timer_cb || multi->dead) return CURLM_OK; - if(multi_timeout(multi, &expire_ts, &timeout_ms)) { - return CURLM_OK; - } + multi_timeout(multi, &expire_ts, &timeout_ms); if(timeout_ms < 0 && multi->last_timeout_ms < 0) { /* nothing to do */ @@ -3486,11 +3464,10 @@ CURLMcode Curl_update_timer(struct Curl_multi *multi) set_value = TRUE; } else if(multi->last_timeout_ms < 0) { - CURL_TRC_M(multi->admin, "[TIMER] set %ldms, none before", - timeout_ms); + CURL_TRC_M(multi->admin, "[TIMER] set %ldms, none before", timeout_ms); set_value = TRUE; } - else if(curlx_timediff_us(multi->last_expire_ts, expire_ts)) { + else if(curlx_ptimediff_us(&multi->last_expire_ts, &expire_ts)) { /* We had a timeout before and have one now, the absolute timestamp * differs. The relative timeout_ms may be the same, but the starting * point differs. Let the application restart its timer. */ @@ -3523,8 +3500,7 @@ CURLMcode Curl_update_timer(struct Curl_multi *multi) * * Remove a given timestamp from the list of timeouts. */ -static void -multi_deltimeout(struct Curl_easy *data, expire_id eid) +static void multi_deltimeout(struct Curl_easy *data, expire_id eid) { struct Curl_llist_node *e; struct Curl_llist *timeoutlist = &data->state.timeoutlist; @@ -3545,11 +3521,9 @@ multi_deltimeout(struct Curl_easy *data, expire_id eid) * of list is always the timeout nearest in time. * */ -static CURLMcode -multi_addtimeout(struct Curl_easy *data, - struct curltime *stamp, - expire_id eid, - const struct curltime *nowp) +static CURLMcode multi_addtimeout(struct Curl_easy *data, + struct curltime *stamp, + expire_id eid) { struct Curl_llist_node *e; struct time_node *node; @@ -3557,7 +3531,6 @@ multi_addtimeout(struct Curl_easy *data, size_t n; struct Curl_llist *timeoutlist = &data->state.timeoutlist; - (void)nowp; node = &data->state.expires[eid]; /* copy the timestamp and id */ @@ -3569,24 +3542,22 @@ multi_addtimeout(struct Curl_easy *data, /* find the correct spot in the list */ for(e = Curl_llist_head(timeoutlist); e; e = Curl_node_next(e)) { struct time_node *check = Curl_node_elem(e); - timediff_t diff = curlx_timediff(check->time, node->time); + timediff_t diff = curlx_ptimediff_ms(&check->time, &node->time); if(diff > 0) break; prev = e; } - } /* else this is the first timeout on the list */ Curl_llist_insert_next(timeoutlist, prev, node, &node->list); CURL_TRC_TIMER(data, eid, "set for %" FMT_TIMEDIFF_T "ns", - curlx_timediff_us(node->time, *nowp)); + curlx_ptimediff_us(&node->time, Curl_pgrs_now(data))); return CURLM_OK; } void Curl_expire_ex(struct Curl_easy *data, - const struct curltime *nowp, timediff_t milli, expire_id id) { struct Curl_multi *multi = data->multi; @@ -3600,9 +3571,9 @@ void Curl_expire_ex(struct Curl_easy *data, DEBUGASSERT(id < EXPIRE_LAST); - set = *nowp; - set.tv_sec += (time_t)(milli/1000); /* might be a 64 to 32 bits conversion */ - set.tv_usec += (int)(milli%1000)*1000; + set = *Curl_pgrs_now(data); + set.tv_sec += (time_t)(milli / 1000); /* may be a 64 to 32-bit conversion */ + set.tv_usec += (int)(milli % 1000) * 1000; if(set.tv_usec >= 1000000) { set.tv_sec++; @@ -3614,13 +3585,13 @@ void Curl_expire_ex(struct Curl_easy *data, /* Add it to the timer list. It must stay in the list until it has expired in case we need to recompute the minimum timer later. */ - multi_addtimeout(data, &set, id, nowp); + multi_addtimeout(data, &set, id); if(curr_expire->tv_sec || curr_expire->tv_usec) { /* This means that the struct is added as a node in the splay tree. Compare if the new time is earlier, and only remove-old/add-new if it is. */ - timediff_t diff = curlx_timediff(set, *curr_expire); + timediff_t diff = curlx_ptimediff_ms(&set, curr_expire); int rc; if(diff > 0) { @@ -3641,7 +3612,7 @@ void Curl_expire_ex(struct Curl_easy *data, value since it is our local minimum. */ *curr_expire = set; Curl_splayset(&data->state.timenode, data); - multi->timetree = Curl_splayinsert(*curr_expire, multi->timetree, + multi->timetree = Curl_splayinsert(curr_expire, multi->timetree, &data->state.timenode); } @@ -3658,8 +3629,7 @@ void Curl_expire_ex(struct Curl_easy *data, */ void Curl_expire(struct Curl_easy *data, timediff_t milli, expire_id id) { - struct curltime now = curlx_now(); - Curl_expire_ex(data, &now, milli, id); + Curl_expire_ex(data, milli, id); } /* @@ -3729,8 +3699,8 @@ static void move_pending_to_connect(struct Curl_multi *multi, DEBUGASSERT(data->mstate == MSTATE_PENDING); /* Remove this node from the pending set, add into process set */ - Curl_uint_bset_remove(&multi->pending, data->mid); - Curl_uint_bset_add(&multi->process, data->mid); + Curl_uint32_bset_remove(&multi->pending, data->mid); + Curl_uint32_bset_add(&multi->process, data->mid); multistate(data, MSTATE_CONNECT); Curl_multi_mark_dirty(data); /* make it run */ @@ -3752,8 +3722,8 @@ static void move_pending_to_connect(struct Curl_multi *multi, */ static void process_pending_handles(struct Curl_multi *multi) { - unsigned int mid; - if(Curl_uint_bset_first(&multi->pending, &mid)) { + uint32_t mid; + if(Curl_uint32_bset_first(&multi->pending, &mid)) { do { struct Curl_easy *data = Curl_multi_get_easy(multi, mid); if(data) { @@ -3761,10 +3731,9 @@ static void process_pending_handles(struct Curl_multi *multi) break; } /* transfer no longer known, should not happen */ - Curl_uint_bset_remove(&multi->pending, mid); + Curl_uint32_bset_remove(&multi->pending, mid); DEBUGASSERT(0); - } - while(Curl_uint_bset_next(&multi->pending, mid, &mid)); + } while(Curl_uint32_bset_next(&multi->pending, mid, &mid)); } } @@ -3789,19 +3758,18 @@ CURL **curl_multi_get_handles(CURLM *m) { struct Curl_multi *multi = m; void *entry; - unsigned int count = Curl_uint_tbl_count(&multi->xfers); - CURL **a = malloc(sizeof(struct Curl_easy *) * (count + 1)); + unsigned int count = Curl_uint32_tbl_count(&multi->xfers); + CURL **a = curlx_malloc(sizeof(struct Curl_easy *) * (count + 1)); if(a) { unsigned int i = 0, mid; - if(Curl_uint_tbl_first(&multi->xfers, &mid, &entry)) { + if(Curl_uint32_tbl_first(&multi->xfers, &mid, &entry)) { do { struct Curl_easy *data = entry; DEBUGASSERT(i < count); if(!data->state.internal) a[i++] = data; - } - while(Curl_uint_tbl_next(&multi->xfers, mid, &mid, &entry)); + } while(Curl_uint32_tbl_next(&multi->xfers, mid, &mid, &entry)); } a[i] = NULL; /* last entry is a NULL */ } @@ -3813,6 +3781,7 @@ CURLMcode curl_multi_get_offt(CURLM *m, curl_off_t *pvalue) { struct Curl_multi *multi = m; + uint32_t n; if(!GOOD_MULTI_HANDLE(multi)) return CURLM_BAD_HANDLE; @@ -3820,21 +3789,23 @@ CURLMcode curl_multi_get_offt(CURLM *m, return CURLM_BAD_FUNCTION_ARGUMENT; switch(info) { - case CURLMINFO_XFERS_CURRENT: { - unsigned int n = Curl_uint_tbl_count(&multi->xfers); + case CURLMINFO_XFERS_CURRENT: + n = Curl_uint32_tbl_count(&multi->xfers); if(n && multi->admin) --n; *pvalue = (curl_off_t)n; return CURLM_OK; - } case CURLMINFO_XFERS_RUNNING: - *pvalue = (curl_off_t)Curl_uint_bset_count(&multi->process); + n = Curl_uint32_bset_count(&multi->process); + if(n && Curl_uint32_bset_contains(&multi->process, multi->admin->mid)) + --n; + *pvalue = (curl_off_t)n; return CURLM_OK; case CURLMINFO_XFERS_PENDING: - *pvalue = (curl_off_t)Curl_uint_bset_count(&multi->pending); + *pvalue = (curl_off_t)Curl_uint32_bset_count(&multi->pending); return CURLM_OK; case CURLMINFO_XFERS_DONE: - *pvalue = (curl_off_t)Curl_uint_bset_count(&multi->msgsent); + *pvalue = (curl_off_t)Curl_uint32_bset_count(&multi->msgsent); return CURLM_OK; case CURLMINFO_XFERS_ADDED: *pvalue = multi->xfers_total_ever; @@ -3868,16 +3839,16 @@ CURLcode Curl_multi_xfer_buf_borrow(struct Curl_easy *data, if(data->multi->xfer_buf && data->set.buffer_size > data->multi->xfer_buf_len) { /* not large enough, get a new one */ - free(data->multi->xfer_buf); + curlx_free(data->multi->xfer_buf); data->multi->xfer_buf = NULL; data->multi->xfer_buf_len = 0; } if(!data->multi->xfer_buf) { - data->multi->xfer_buf = malloc((size_t)data->set.buffer_size); + data->multi->xfer_buf = curlx_malloc(curlx_uitouz(data->set.buffer_size)); if(!data->multi->xfer_buf) { - failf(data, "could not allocate xfer_buf of %zu bytes", - (size_t)data->set.buffer_size); + failf(data, "could not allocate xfer_buf of %u bytes", + data->set.buffer_size); return CURLE_OUT_OF_MEMORY; } data->multi->xfer_buf_len = data->set.buffer_size; @@ -3921,16 +3892,17 @@ CURLcode Curl_multi_xfer_ulbuf_borrow(struct Curl_easy *data, if(data->multi->xfer_ulbuf && data->set.upload_buffer_size > data->multi->xfer_ulbuf_len) { /* not large enough, get a new one */ - free(data->multi->xfer_ulbuf); + curlx_free(data->multi->xfer_ulbuf); data->multi->xfer_ulbuf = NULL; data->multi->xfer_ulbuf_len = 0; } if(!data->multi->xfer_ulbuf) { - data->multi->xfer_ulbuf = malloc((size_t)data->set.upload_buffer_size); + data->multi->xfer_ulbuf = + curlx_malloc(curlx_uitouz(data->set.upload_buffer_size)); if(!data->multi->xfer_ulbuf) { - failf(data, "could not allocate xfer_ulbuf of %zu bytes", - (size_t)data->set.upload_buffer_size); + failf(data, "could not allocate xfer_ulbuf of %u bytes", + data->set.upload_buffer_size); return CURLE_OUT_OF_MEMORY; } data->multi->xfer_ulbuf_len = data->set.upload_buffer_size; @@ -3968,13 +3940,13 @@ CURLcode Curl_multi_xfer_sockbuf_borrow(struct Curl_easy *data, if(data->multi->xfer_sockbuf && blen > data->multi->xfer_sockbuf_len) { /* not large enough, get a new one */ - free(data->multi->xfer_sockbuf); + curlx_free(data->multi->xfer_sockbuf); data->multi->xfer_sockbuf = NULL; data->multi->xfer_sockbuf_len = 0; } if(!data->multi->xfer_sockbuf) { - data->multi->xfer_sockbuf = malloc(blen); + data->multi->xfer_sockbuf = curlx_malloc(blen); if(!data->multi->xfer_sockbuf) { failf(data, "could not allocate xfer_sockbuf of %zu bytes", blen); return CURLE_OUT_OF_MEMORY; @@ -4011,14 +3983,14 @@ static void multi_xfer_bufs_free(struct Curl_multi *multi) } struct Curl_easy *Curl_multi_get_easy(struct Curl_multi *multi, - unsigned int mid) + uint32_t mid) { - struct Curl_easy *data = mid ? Curl_uint_tbl_get(&multi->xfers, mid) : NULL; + struct Curl_easy *data = Curl_uint32_tbl_get(&multi->xfers, mid); if(data && GOOD_EASY_HANDLE(data)) return data; CURL_TRC_M(multi->admin, "invalid easy handle in xfer table for mid=%u", mid); - Curl_uint_tbl_remove(&multi->xfers, mid); + Curl_uint32_tbl_remove(&multi->xfers, mid); return NULL; } @@ -4029,14 +4001,14 @@ unsigned int Curl_multi_xfers_running(struct Curl_multi *multi) void Curl_multi_mark_dirty(struct Curl_easy *data) { - if(data->multi && data->mid != UINT_MAX) - Curl_uint_bset_add(&data->multi->dirty, data->mid); + if(data->multi && data->mid != UINT32_MAX) + Curl_uint32_bset_add(&data->multi->dirty, data->mid); } void Curl_multi_clear_dirty(struct Curl_easy *data) { - if(data->multi && data->mid != UINT_MAX) - Curl_uint_bset_remove(&data->multi->dirty, data->mid); + if(data->multi && data->mid != UINT32_MAX) + Curl_uint32_bset_remove(&data->multi->dirty, data->mid); } CURLMcode curl_multi_notify_enable(CURLM *m, unsigned int notification) @@ -4058,7 +4030,7 @@ CURLMcode curl_multi_notify_disable(CURLM *m, unsigned int notification) } #ifdef DEBUGBUILD -static void multi_xfer_dump(struct Curl_multi *multi, unsigned int mid, +static void multi_xfer_dump(struct Curl_multi *multi, uint32_t mid, void *entry) { struct Curl_easy *data = entry; @@ -4072,20 +4044,20 @@ static void multi_xfer_dump(struct Curl_multi *multi, unsigned int mid, ", url=%s\n", mid, (data->magic == CURLEASY_MAGIC_NUMBER) ? "GOOD" : "BAD!", - (void *)data, data->id, data->state.url); + (void *)data, data->id, Curl_bufref_ptr(&data->state.url)); } } static void multi_xfer_tbl_dump(struct Curl_multi *multi) { - unsigned int mid; + uint32_t mid; void *entry; curl_mfprintf(stderr, "=== multi xfer table (count=%u, capacity=%u\n", - Curl_uint_tbl_count(&multi->xfers), - Curl_uint_tbl_capacity(&multi->xfers)); - if(Curl_uint_tbl_first(&multi->xfers, &mid, &entry)) { + Curl_uint32_tbl_count(&multi->xfers), + Curl_uint32_tbl_capacity(&multi->xfers)); + if(Curl_uint32_tbl_first(&multi->xfers, &mid, &entry)) { multi_xfer_dump(multi, mid, entry); - while(Curl_uint_tbl_next(&multi->xfers, mid, &mid, &entry)) + while(Curl_uint32_tbl_next(&multi->xfers, mid, &mid, &entry)) multi_xfer_dump(multi, mid, entry); } curl_mfprintf(stderr, "===\n"); diff --git a/lib/multi_ev.c b/lib/multi_ev.c index ff755caa6aa3..5d55ed8ebcee 100644 --- a/lib/multi_ev.c +++ b/lib/multi_ev.c @@ -24,8 +24,6 @@ #include "curl_setup.h" -#include - #include "urldata.h" #include "url.h" #include "cfilters.h" @@ -36,14 +34,7 @@ #include "select.h" #include "uint-bset.h" #include "uint-spbset.h" -#include "uint-table.h" -#include "curlx/warnless.h" #include "multihandle.h" -#include "socks.h" - -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" static void mev_in_callback(struct Curl_multi *multi, bool value) @@ -55,7 +46,7 @@ static void mev_in_callback(struct Curl_multi *multi, bool value) * what to supervise (CURL_POLL_IN/CURL_POLL_OUT/CURL_POLL_REMOVE) */ struct mev_sh_entry { - struct uint_spbset xfers; /* bitset of transfers `mid`s on this socket */ + struct uint32_spbset xfers; /* bitset of transfers `mid`s on this socket */ struct connectdata *conn; /* connection using this socket or NULL */ void *user_data; /* libcurl app data via curl_multi_assign() */ unsigned int action; /* CURL_POLL_IN/CURL_POLL_OUT we last told the @@ -68,7 +59,7 @@ struct mev_sh_entry { static size_t mev_sh_entry_hash(void *key, size_t key_length, size_t slots_num) { - curl_socket_t fd = *((curl_socket_t *) key); + curl_socket_t fd = *((curl_socket_t *)key); (void)key_length; return (fd % (curl_socket_t)slots_num); } @@ -76,21 +67,22 @@ static size_t mev_sh_entry_hash(void *key, size_t key_length, size_t slots_num) static size_t mev_sh_entry_compare(void *k1, size_t k1_len, void *k2, size_t k2_len) { - (void)k1_len; (void)k2_len; - return (*((curl_socket_t *) k1)) == (*((curl_socket_t *) k2)); + (void)k1_len; + (void)k2_len; + return (*((curl_socket_t *)k1)) == (*((curl_socket_t *)k2)); } /* sockhash entry destructor callback */ static void mev_sh_entry_dtor(void *freethis) { struct mev_sh_entry *entry = (struct mev_sh_entry *)freethis; - Curl_uint_spbset_destroy(&entry->xfers); - free(entry); + Curl_uint32_spbset_destroy(&entry->xfers); + curlx_free(entry); } /* look up a given socket in the socket hash, skip invalid sockets */ -static struct mev_sh_entry * -mev_sh_entry_get(struct Curl_hash *sh, curl_socket_t s) +static struct mev_sh_entry *mev_sh_entry_get(struct Curl_hash *sh, + curl_socket_t s) { if(s != CURL_SOCKET_BAD) { /* only look for proper sockets */ @@ -100,8 +92,8 @@ mev_sh_entry_get(struct Curl_hash *sh, curl_socket_t s) } /* make sure this socket is present in the hash for this handle */ -static struct mev_sh_entry * -mev_sh_entry_add(struct Curl_hash *sh, curl_socket_t s) +static struct mev_sh_entry *mev_sh_entry_add(struct Curl_hash *sh, + curl_socket_t s) { struct mev_sh_entry *there = mev_sh_entry_get(sh, s); struct mev_sh_entry *check; @@ -112,11 +104,11 @@ mev_sh_entry_add(struct Curl_hash *sh, curl_socket_t s) } /* not present, add it */ - check = calloc(1, sizeof(struct mev_sh_entry)); + check = curlx_calloc(1, sizeof(struct mev_sh_entry)); if(!check) return NULL; /* major failure */ - Curl_uint_spbset_init(&check->xfers); + Curl_uint32_spbset_init(&check->xfers); /* make/add new hash entry */ if(!Curl_hash_add(sh, (char *)&s, sizeof(curl_socket_t), check)) { @@ -135,13 +127,13 @@ static void mev_sh_entry_kill(struct Curl_multi *multi, curl_socket_t s) static size_t mev_sh_entry_user_count(struct mev_sh_entry *e) { - return Curl_uint_spbset_count(&e->xfers) + (e->conn ? 1 : 0); + return Curl_uint32_spbset_count(&e->xfers) + (e->conn ? 1 : 0); } static bool mev_sh_entry_xfer_known(struct mev_sh_entry *e, struct Curl_easy *data) { - return Curl_uint_spbset_contains(&e->xfers, data->mid); + return Curl_uint32_spbset_contains(&e->xfers, data->mid); } static bool mev_sh_entry_conn_known(struct mev_sh_entry *e, @@ -155,7 +147,7 @@ static bool mev_sh_entry_xfer_add(struct mev_sh_entry *e, { /* detect weird values */ DEBUGASSERT(mev_sh_entry_user_count(e) < 100000); - return Curl_uint_spbset_add(&e->xfers, data->mid); + return Curl_uint32_spbset_add(&e->xfers, data->mid); } static bool mev_sh_entry_conn_add(struct mev_sh_entry *e, @@ -170,13 +162,12 @@ static bool mev_sh_entry_conn_add(struct mev_sh_entry *e, return TRUE; } - static bool mev_sh_entry_xfer_remove(struct mev_sh_entry *e, struct Curl_easy *data) { - bool present = Curl_uint_spbset_contains(&e->xfers, data->mid); + bool present = Curl_uint32_spbset_contains(&e->xfers, data->mid); if(present) - Curl_uint_spbset_remove(&e->xfers, data->mid); + Curl_uint32_spbset_remove(&e->xfers, data->mid); return present; } @@ -206,8 +197,7 @@ static CURLMcode mev_forget_socket(struct Curl_multi *multi, /* We managed this socket before, tell the socket callback to forget it. */ if(entry->announced && multi->socket_cb) { - CURL_TRC_M(data, "ev %s, call(fd=%" FMT_SOCKET_T ", ev=REMOVE)", - cause, s); + CURL_TRC_M(data, "ev %s, call(fd=%" FMT_SOCKET_T ", ev=REMOVE)", cause, s); mev_in_callback(multi, TRUE); rc = multi->socket_cb(data, s, CURL_POLL_REMOVE, multi->socket_userp, entry->user_data); @@ -340,7 +330,7 @@ static CURLMcode mev_pollset_diff(struct Curl_multi *multi, /* What was the previous action the transfer had regarding this socket? * If the transfer is new to the socket, disregard the information * in `last_poll`, because the socket might have been destroyed and - * reopened. We'd have cleared the sh_entry for that, but the socket + * reopened. We would have cleared the sh_entry for that, but the socket * might still be mentioned in the hashed pollsets. */ last_action = 0; if(first_time) { @@ -356,7 +346,7 @@ static CURLMcode mev_pollset_diff(struct Curl_multi *multi, ", total=%u/%d (xfer/conn)", s, conn ? "connection" : "transfer", conn ? conn->connection_id : data->mid, - Curl_uint_spbset_count(&entry->xfers), + Curl_uint32_spbset_count(&entry->xfers), entry->conn ? 1 : 0); } else { @@ -424,7 +414,7 @@ static CURLMcode mev_pollset_diff(struct Curl_multi *multi, return mresult; CURL_TRC_M(data, "ev entry fd=%" FMT_SOCKET_T ", removed transfer, " "total=%u/%d (xfer/conn)", s, - Curl_uint_spbset_count(&entry->xfers), + Curl_uint32_spbset_count(&entry->xfers), entry->conn ? 1 : 0); } else { @@ -446,12 +436,11 @@ static void mev_pollset_dtor(void *key, size_t klen, void *entry) (void)klen; if(ps) { Curl_pollset_cleanup(ps); - free(ps); + curlx_free(ps); } } -static struct easy_pollset* -mev_add_new_conn_pollset(struct connectdata *conn) +static struct easy_pollset *mev_add_new_conn_pollset(struct connectdata *conn) { struct easy_pollset *ps; @@ -463,8 +452,7 @@ mev_add_new_conn_pollset(struct connectdata *conn) return ps; } -static struct easy_pollset* -mev_add_new_xfer_pollset(struct Curl_easy *data) +static struct easy_pollset *mev_add_new_xfer_pollset(struct Curl_easy *data) { struct easy_pollset *ps; @@ -476,9 +464,8 @@ mev_add_new_xfer_pollset(struct Curl_easy *data) return ps; } -static struct easy_pollset * -mev_get_last_pollset(struct Curl_easy *data, - struct connectdata *conn) +static struct easy_pollset *mev_get_last_pollset(struct Curl_easy *data, + struct connectdata *conn) { if(data) { if(conn) @@ -493,7 +480,7 @@ static CURLMcode mev_assess(struct Curl_multi *multi, struct connectdata *conn) { struct easy_pollset ps, *last_ps; - CURLMcode res = CURLM_OK; + CURLMcode mresult = CURLM_OK; if(!multi || !multi->socket_cb) return CURLM_OK; @@ -502,13 +489,13 @@ static CURLMcode mev_assess(struct Curl_multi *multi, if(conn) { CURLcode r = Curl_conn_adjust_pollset(data, conn, &ps); if(r) { - res = (r == CURLE_OUT_OF_MEMORY) ? - CURLM_OUT_OF_MEMORY : CURLM_INTERNAL_ERROR; + mresult = (r == CURLE_OUT_OF_MEMORY) ? + CURLM_OUT_OF_MEMORY : CURLM_INTERNAL_ERROR; goto out; } } else - Curl_multi_pollset(data, &ps, "ev assess"); + Curl_multi_pollset(data, &ps); last_ps = mev_get_last_pollset(data, conn); if(!last_ps && ps.n) { @@ -517,18 +504,18 @@ static CURLMcode mev_assess(struct Curl_multi *multi, else last_ps = mev_add_new_xfer_pollset(data); if(!last_ps) { - res = CURLM_OUT_OF_MEMORY; + mresult = CURLM_OUT_OF_MEMORY; goto out; } } if(last_ps) - res = mev_pollset_diff(multi, data, conn, &ps, last_ps); + mresult = mev_pollset_diff(multi, data, conn, &ps, last_ps); else DEBUGASSERT(!ps.n); out: Curl_pollset_cleanup(&ps); - return res; + return mresult; } CURLMcode Curl_multi_ev_assess_xfer(struct Curl_multi *multi, @@ -545,23 +532,22 @@ CURLMcode Curl_multi_ev_assess_conn(struct Curl_multi *multi, } CURLMcode Curl_multi_ev_assess_xfer_bset(struct Curl_multi *multi, - struct uint_bset *set) + struct uint32_bset *set) { - unsigned int mid; - CURLMcode result = CURLM_OK; + uint32_t mid; + CURLMcode mresult = CURLM_OK; - if(multi && multi->socket_cb && Curl_uint_bset_first(set, &mid)) { + if(multi && multi->socket_cb && Curl_uint32_bset_first(set, &mid)) { do { struct Curl_easy *data = Curl_multi_get_easy(multi, mid); - if(data) - result = Curl_multi_ev_assess_xfer(multi, data); - } - while(!result && Curl_uint_bset_next(set, mid, &mid)); + if(data) { + mresult = Curl_multi_ev_assess_xfer(multi, data); + } + } while(!mresult && Curl_uint32_bset_next(set, mid, &mid)); } - return result; + return mresult; } - CURLMcode Curl_multi_ev_assign(struct Curl_multi *multi, curl_socket_t s, void *user_data) @@ -574,8 +560,7 @@ CURLMcode Curl_multi_ev_assign(struct Curl_multi *multi, } void Curl_multi_ev_dirty_xfers(struct Curl_multi *multi, - curl_socket_t s, - bool *run_cpool) + curl_socket_t s) { struct mev_sh_entry *entry; @@ -589,9 +574,9 @@ void Curl_multi_ev_dirty_xfers(struct Curl_multi *multi, and just move on. */ if(entry) { struct Curl_easy *data; - unsigned int mid; + uint32_t mid; - if(Curl_uint_spbset_first(&entry->xfers, &mid)) { + if(Curl_uint32_spbset_first(&entry->xfers, &mid)) { do { data = Curl_multi_get_easy(multi, mid); if(data) { @@ -599,14 +584,13 @@ void Curl_multi_ev_dirty_xfers(struct Curl_multi *multi, } else { CURL_TRC_M(multi->admin, "socket transfer %u no longer found", mid); - Curl_uint_spbset_remove(&entry->xfers, mid); + Curl_uint32_spbset_remove(&entry->xfers, mid); } - } - while(Curl_uint_spbset_next(&entry->xfers, mid, &mid)); + } while(Curl_uint32_spbset_next(&entry->xfers, mid, &mid)); } if(entry->conn) - *run_cpool = TRUE; + Curl_multi_mark_dirty(multi->admin); } } diff --git a/lib/multi_ev.h b/lib/multi_ev.h index 20c1aeac81a6..4e5b2a454d26 100644 --- a/lib/multi_ev.h +++ b/lib/multi_ev.h @@ -29,7 +29,7 @@ struct Curl_easy; struct Curl_multi; struct easy_pollset; -struct uint_bset; +struct uint32_bset; /* meta key for event pollset at easy handle or connection */ #define CURL_META_MEV_POLLSET "meta:mev:ps" @@ -55,7 +55,7 @@ CURLMcode Curl_multi_ev_assess_xfer(struct Curl_multi *multi, struct Curl_easy *data); /* Assess all easy handles on the list */ CURLMcode Curl_multi_ev_assess_xfer_bset(struct Curl_multi *multi, - struct uint_bset *set); + struct uint32_bset *set); /* Assess the connection by getting its current pollset */ CURLMcode Curl_multi_ev_assess_conn(struct Curl_multi *multi, struct Curl_easy *data, @@ -63,8 +63,7 @@ CURLMcode Curl_multi_ev_assess_conn(struct Curl_multi *multi, /* Mark all transfers tied to the given socket as dirty */ void Curl_multi_ev_dirty_xfers(struct Curl_multi *multi, - curl_socket_t s, - bool *run_cpool); + curl_socket_t s); /* Socket will be closed, forget anything we know about it. */ void Curl_multi_ev_socket_done(struct Curl_multi *multi, diff --git a/lib/multi_ntfy.c b/lib/multi_ntfy.c index fe7cc0503a76..c41743719e92 100644 --- a/lib/multi_ntfy.c +++ b/lib/multi_ntfy.c @@ -24,26 +24,19 @@ #include "curl_setup.h" -#include - #include "urldata.h" #include "curl_trc.h" #include "multihandle.h" #include "multiif.h" #include "multi_ntfy.h" -/* The last 3 #include files should be in this order */ -#include "curl_printf.h" -#include "curl_memory.h" -#include "memdebug.h" - struct mntfy_entry { - unsigned int mid; - unsigned int type; + uint32_t mid; + uint32_t type; }; -#define CURL_MNTFY_CHUNK_SIZE 128 +#define CURL_MNTFY_CHUNK_SIZE 128 struct mntfy_chunk { struct mntfy_chunk *next; @@ -54,12 +47,12 @@ struct mntfy_chunk { static struct mntfy_chunk *mnfty_chunk_create(void) { - return calloc(1, sizeof(struct mntfy_chunk)); + return curlx_calloc(1, sizeof(struct mntfy_chunk)); } static void mnfty_chunk_destroy(struct mntfy_chunk *chunk) { - free(chunk); + curlx_free(chunk); } static void mnfty_chunk_reset(struct mntfy_chunk *chunk) @@ -69,7 +62,7 @@ static void mnfty_chunk_reset(struct mntfy_chunk *chunk) static bool mntfy_chunk_append(struct mntfy_chunk *chunk, struct Curl_easy *data, - unsigned int type) + uint32_t type) { struct mntfy_entry *e; @@ -116,7 +109,7 @@ static void mntfy_chunk_dispatch_all(struct Curl_multi *multi, e = &chunk->entries[chunk->r_offset]; data = e->mid ? Curl_multi_get_easy(multi, e->mid) : multi->admin; /* only when notification has not been disabled in the meantime */ - if(data && Curl_uint_bset_contains(&multi->ntfy.enabled, e->type)) { + if(data && Curl_uint32_bset_contains(&multi->ntfy.enabled, e->type)) { /* this may cause new notifications to be added! */ CURL_TRC_M(multi->admin, "[NTFY] dispatch %d to xfer %u", e->type, e->mid); @@ -132,12 +125,12 @@ static void mntfy_chunk_dispatch_all(struct Curl_multi *multi, void Curl_mntfy_init(struct Curl_multi *multi) { memset(&multi->ntfy, 0, sizeof(multi->ntfy)); - Curl_uint_bset_init(&multi->ntfy.enabled); + Curl_uint32_bset_init(&multi->ntfy.enabled); } CURLMcode Curl_mntfy_resize(struct Curl_multi *multi) { - if(Curl_uint_bset_resize(&multi->ntfy.enabled, CURLMNOTIFY_EASY_DONE + 1)) + if(Curl_uint32_bset_resize(&multi->ntfy.enabled, CURLMNOTIFY_EASY_DONE + 1)) return CURLM_OUT_OF_MEMORY; return CURLM_OK; } @@ -150,14 +143,14 @@ void Curl_mntfy_cleanup(struct Curl_multi *multi) mnfty_chunk_destroy(chunk); } multi->ntfy.tail = NULL; - Curl_uint_bset_destroy(&multi->ntfy.enabled); + Curl_uint32_bset_destroy(&multi->ntfy.enabled); } CURLMcode Curl_mntfy_enable(struct Curl_multi *multi, unsigned int type) { if(type > CURLMNOTIFY_EASY_DONE) return CURLM_UNKNOWN_OPTION; - Curl_uint_bset_add(&multi->ntfy.enabled, type); + Curl_uint32_bset_add(&multi->ntfy.enabled, type); return CURLM_OK; } @@ -165,7 +158,7 @@ CURLMcode Curl_mntfy_disable(struct Curl_multi *multi, unsigned int type) { if(type > CURLMNOTIFY_EASY_DONE) return CURLM_UNKNOWN_OPTION; - Curl_uint_bset_remove(&multi->ntfy.enabled, type); + Curl_uint32_bset_remove(&multi->ntfy.enabled, (uint32_t)type); return CURLM_OK; } @@ -173,14 +166,15 @@ void Curl_mntfy_add(struct Curl_easy *data, unsigned int type) { struct Curl_multi *multi = data ? data->multi : NULL; if(multi && multi->ntfy.ntfy_cb && !multi->ntfy.failure && - Curl_uint_bset_contains(&multi->ntfy.enabled, type)) { + Curl_uint32_bset_contains(&multi->ntfy.enabled, (uint32_t)type)) { /* append to list of outstanding notifications */ struct mntfy_chunk *tail = mntfy_non_full_tail(&multi->ntfy); - CURL_TRC_M(data, "[NTFY] add %d for xfer %u", type, data->mid); + CURL_TRC_M(data, "[NTFY] add %d for xfer %u", type, data->mid); if(tail) - mntfy_chunk_append(tail, data, type); + mntfy_chunk_append(tail, data, (uint32_t)type); else multi->ntfy.failure = CURLM_OUT_OF_MEMORY; + multi->ntfy.has_entries = TRUE; } } @@ -204,9 +198,11 @@ CURLMcode Curl_mntfy_dispatch_all(struct Curl_multi *multi) multi->in_ntfy_callback = FALSE; if(multi->ntfy.failure) { - CURLMcode result = multi->ntfy.failure; + CURLMcode mresult = multi->ntfy.failure; multi->ntfy.failure = CURLM_OK; /* reset, once delivered */ - return result; + return mresult; } + else + multi->ntfy.has_entries = FALSE; return CURLM_OK; } diff --git a/lib/multi_ntfy.h b/lib/multi_ntfy.h index d920b3295d4b..2f1f34435756 100644 --- a/lib/multi_ntfy.h +++ b/lib/multi_ntfy.h @@ -32,10 +32,11 @@ struct Curl_multi; struct curl_multi_ntfy { curl_notify_callback ntfy_cb; void *ntfy_cb_data; - struct uint_bset enabled; - CURLMcode failure; + struct uint32_bset enabled; struct mntfy_chunk *head; struct mntfy_chunk *tail; + CURLMcode failure; + BIT(has_entries); }; void Curl_mntfy_init(struct Curl_multi *multi); @@ -47,11 +48,14 @@ CURLMcode Curl_mntfy_disable(struct Curl_multi *multi, unsigned int type); void Curl_mntfy_add(struct Curl_easy *data, unsigned int type); -#define CURLM_NTFY(d,t) \ - do { if((d) && (d)->multi && (d)->multi->ntfy.ntfy_cb) \ - Curl_mntfy_add((d), (t)); } while(0) +#define CURLM_NTFY(d, t) \ + do { \ + if((d) && (d)->multi && (d)->multi->ntfy.ntfy_cb) \ + Curl_mntfy_add((d), (t)); \ + } while(0) -CURLMcode Curl_mntfy_dispatch_all(struct Curl_multi *multi); +#define CURL_MNTFY_HAS_ENTRIES(m) ((m)->ntfy.has_entries) +CURLMcode Curl_mntfy_dispatch_all(struct Curl_multi *multi); #endif /* HEADER_CURL_MULTI_NTFY_H */ diff --git a/lib/multihandle.h b/lib/multihandle.h index 69f977bb94ed..2bf06322a899 100644 --- a/lib/multihandle.h +++ b/lib/multihandle.h @@ -51,26 +51,23 @@ struct Curl_message { */ typedef enum { MSTATE_INIT, /* 0 - start in this state */ - MSTATE_PENDING, /* 1 - no connections, waiting for one */ - MSTATE_SETUP, /* 2 - start a new transfer */ - MSTATE_CONNECT, /* 3 - resolve/connect has been sent off */ - MSTATE_RESOLVING, /* 4 - awaiting the resolve to finalize */ - MSTATE_CONNECTING, /* 5 - awaiting the TCP connect to finalize */ - MSTATE_TUNNELING, /* 6 - awaiting HTTPS proxy SSL initialization to - complete and/or proxy CONNECT to finalize */ - MSTATE_PROTOCONNECT, /* 7 - initiate protocol connect procedure */ - MSTATE_PROTOCONNECTING, /* 8 - completing the protocol-specific connect - phase */ - MSTATE_DO, /* 9 - start send off the request (part 1) */ - MSTATE_DOING, /* 10 - sending off the request (part 1) */ - MSTATE_DOING_MORE, /* 11 - send off the request (part 2) */ - MSTATE_DID, /* 12 - done sending off request */ - MSTATE_PERFORMING, /* 13 - transfer data */ - MSTATE_RATELIMITING, /* 14 - wait because limit-rate exceeded */ - MSTATE_DONE, /* 15 - post data transfer operation */ - MSTATE_COMPLETED, /* 16 - operation complete */ - MSTATE_MSGSENT, /* 17 - the operation complete message is sent */ - MSTATE_LAST /* 18 - not a true state, never use this */ + MSTATE_PENDING, /* no connections, waiting for one */ + MSTATE_SETUP, /* start a new transfer */ + MSTATE_CONNECT, /* resolve/connect has been sent off */ + MSTATE_RESOLVING, /* awaiting the resolve to finalize */ + MSTATE_CONNECTING, /* awaiting the TCP connect to finalize */ + MSTATE_PROTOCONNECT, /* initiate protocol connect procedure */ + MSTATE_PROTOCONNECTING, /* completing the protocol-specific connect phase */ + MSTATE_DO, /* start send off the request (part 1) */ + MSTATE_DOING, /* sending off the request (part 1) */ + MSTATE_DOING_MORE, /* send off the request (part 2) */ + MSTATE_DID, /* done sending off request */ + MSTATE_PERFORMING, /* transfer data */ + MSTATE_RATELIMITING, /* wait because limit-rate exceeded */ + MSTATE_DONE, /* post data transfer operation */ + MSTATE_COMPLETED, /* operation complete */ + MSTATE_MSGSENT, /* the operation complete message is sent */ + MSTATE_LAST /* not a true state, never use this */ } CURLMstate; #define CURLPIPE_ANY (CURLPIPE_MULTIPLEX) @@ -91,12 +88,12 @@ struct Curl_multi { unsigned int xfers_alive; /* amount of added transfers that have not yet reached COMPLETE state */ curl_off_t xfers_total_ever; /* total of added transfers, ever. */ - struct uint_tbl xfers; /* transfers added to this multi */ + struct uint32_tbl xfers; /* transfers added to this multi */ /* Each transfer's mid may be present in at most one of these */ - struct uint_bset process; /* transfer being processed */ - struct uint_bset dirty; /* transfer to be run NOW, e.g. ASAP. */ - struct uint_bset pending; /* transfers in waiting (conn limit etc.) */ - struct uint_bset msgsent; /* transfers done with message for application */ + struct uint32_bset process; /* transfer being processed */ + struct uint32_bset dirty; /* transfer to be run NOW, e.g. ASAP. */ + struct uint32_bset pending; /* transfers in waiting (conn limit etc.) */ + struct uint32_bset msgsent; /* transfers done with message for application */ struct Curl_llist msglist; /* a list of messages from completed transfers */ @@ -119,6 +116,8 @@ struct Curl_multi { struct PslCache psl; #endif + /* current time for transfers running in this multi handle */ + struct curltime now; /* timetree points to the splay-tree of time nodes to figure out expire times of all currently set timers */ struct Curl_tree *timetree; @@ -149,11 +148,10 @@ struct Curl_multi { struct cshutdn cshutdn; /* connection shutdown handling */ struct cpool cpool; /* connection pool (bundles) */ - long max_host_connections; /* if >0, a fixed limit of the maximum number - of connections per host */ - - long max_total_connections; /* if >0, a fixed limit of the maximum number - of connections in total */ + size_t max_host_connections; /* if >0, a fixed limit of the maximum number + of connections per host */ + size_t max_total_connections; /* if >0, a fixed limit of the maximum number + of connections in total */ /* timer callback and user data pointer for the *socket() API */ curl_multi_timer_callback timer_cb; @@ -174,6 +172,9 @@ struct Curl_multi { unsigned int maxconnects; /* if >0, a fixed limit of the maximum number of entries we are allowed to grow the connection cache to */ +#ifdef DEBUGBUILD + unsigned int now_access_count; +#endif #define IPV6_UNKNOWN 0 #define IPV6_DEAD 1 #define IPV6_WORKS 2 diff --git a/lib/multiif.h b/lib/multiif.h index 1423d5a03d0c..f4dc24a3e97a 100644 --- a/lib/multiif.h +++ b/lib/multiif.h @@ -30,7 +30,6 @@ void Curl_expire(struct Curl_easy *data, timediff_t milli, expire_id); void Curl_expire_ex(struct Curl_easy *data, - const struct curltime *nowp, timediff_t milli, expire_id id); bool Curl_expire_clear(struct Curl_easy *data); void Curl_expire_done(struct Curl_easy *data, expire_id id); @@ -68,13 +67,11 @@ CURLMcode Curl_multi_add_perform(struct Curl_multi *multi, struct Curl_easy *data, struct connectdata *conn); - /* Return the value of the CURLMOPT_MAX_CONCURRENT_STREAMS option */ unsigned int Curl_multi_max_concurrent_streams(struct Curl_multi *multi); CURLMcode Curl_multi_pollset(struct Curl_easy *data, - struct easy_pollset *ps, - const char *caller); + struct easy_pollset *ps); /** * Borrow the transfer buffer from the multi, suitable @@ -154,7 +151,7 @@ void Curl_multi_xfer_sockbuf_release(struct Curl_easy *data, char *buf); * Returns NULL if not found. */ struct Curl_easy *Curl_multi_get_easy(struct Curl_multi *multi, - unsigned int mid); + uint32_t mid); /* Get the # of transfers current in process/pending. */ unsigned int Curl_multi_xfers_running(struct Curl_multi *multi); @@ -165,4 +162,6 @@ void Curl_multi_mark_dirty(struct Curl_easy *data); /* Clear transfer from the dirty set. */ void Curl_multi_clear_dirty(struct Curl_easy *data); +void Curl_multi_set_now(struct Curl_multi *multi); + #endif /* HEADER_CURL_MULTIIF_H */ diff --git a/lib/netrc.c b/lib/netrc.c index f06dff8ed515..fe0380066b1b 100644 --- a/lib/netrc.c +++ b/lib/netrc.c @@ -23,6 +23,7 @@ ***************************************************************************/ #include "curl_setup.h" + #ifndef CURL_DISABLE_NETRC #ifdef HAVE_PWD_H @@ -35,17 +36,12 @@ #endif #endif -#include #include "netrc.h" #include "strcase.h" #include "curl_get_line.h" #include "curlx/fopen.h" #include "curlx/strparse.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - /* Get user and password from .netrc when given a machine name */ enum host_lookup_state { @@ -64,8 +60,8 @@ enum found_state { #define FOUND_LOGIN 1 #define FOUND_PASSWORD 2 -#define MAX_NETRC_LINE 16384 -#define MAX_NETRC_FILE (128*1024) +#define MAX_NETRC_LINE 16384 +#define MAX_NETRC_FILE (128 * 1024) #define MAX_NETRC_TOKEN 4096 /* convert a dynbuf call CURLcode error to a NETRCcode error */ @@ -81,22 +77,27 @@ static NETRCcode file2memory(const char *filename, struct dynbuf *filebuf) curlx_dyn_init(&linebuf, MAX_NETRC_LINE); if(file) { + CURLcode result = CURLE_OK; + bool eof; ret = NETRC_OK; - while(Curl_get_line(&linebuf, file)) { - CURLcode result; - const char *line = curlx_dyn_ptr(&linebuf); - /* skip comments on load */ - curlx_str_passblanks(&line); - if(*line == '#') - continue; - result = curlx_dyn_add(filebuf, line); + do { + const char *line; + result = Curl_get_line(&linebuf, file, &eof); + if(!result) { + line = curlx_dyn_ptr(&linebuf); + /* skip comments on load */ + curlx_str_passblanks(&line); + if(*line == '#') + continue; + result = curlx_dyn_add(filebuf, line); + } if(result) { + curlx_dyn_free(filebuf); ret = curl2netrc(result); - goto done; + break; } - } + } while(!eof); } -done: curlx_dyn_free(&linebuf); if(file) curlx_fclose(file); @@ -272,8 +273,8 @@ static NETRCcode parsenetrc(struct store_netrc *store, our_login = !Curl_timestrcmp(login, tok); else { our_login = TRUE; - free(login); - login = strdup(tok); + curlx_free(login); + login = curlx_strdup(tok); if(!login) { retcode = NETRC_OUT_OF_MEMORY; /* allocation failed */ goto out; @@ -283,8 +284,8 @@ static NETRCcode parsenetrc(struct store_netrc *store, keyword = NONE; } else if(keyword == PASSWORD) { - free(password); - password = strdup(tok); + curlx_free(password); + password = curlx_strdup(tok); if(!password) { retcode = NETRC_OUT_OF_MEMORY; /* allocation failed */ goto out; @@ -317,7 +318,7 @@ static NETRCcode parsenetrc(struct store_netrc *store, if(!specific_login) Curl_safefree(login); } - if((found == (FOUND_PASSWORD|FOUND_LOGIN)) && our_login) { + if((found == (FOUND_PASSWORD | FOUND_LOGIN)) && our_login) { done = TRUE; break; } @@ -341,7 +342,7 @@ static NETRCcode parsenetrc(struct store_netrc *store, if(!retcode) { if(!password && our_login) { /* success without a password, set a blank one */ - password = strdup(""); + password = curlx_strdup(""); if(!password) retcode = NETRC_OUT_OF_MEMORY; /* out of memory */ } @@ -357,9 +358,10 @@ static NETRCcode parsenetrc(struct store_netrc *store, } else { curlx_dyn_free(filebuf); + store->loaded = FALSE; if(!specific_login) - free(login); - free(password); + curlx_free(login); + curlx_free(password); } return retcode; @@ -410,8 +412,8 @@ NETRCcode Curl_parsenetrc(struct store_netrc *store, const char *host, } else { struct passwd pw, *pw_res; - if(!getpwuid_r(geteuid(), &pw, pwbuf, sizeof(pwbuf), &pw_res) - && pw_res) { + if(!getpwuid_r(geteuid(), &pw, pwbuf, sizeof(pwbuf), &pw_res) && + pw_res) { home = pw.pw_dir; } #elif defined(HAVE_GETPWUID) && defined(HAVE_GETEUID) @@ -438,25 +440,25 @@ NETRCcode Curl_parsenetrc(struct store_netrc *store, const char *host, filealloc = curl_maprintf("%s%s.netrc", home, DIR_CHAR); if(!filealloc) { - free(homea); + curlx_free(homea); return NETRC_OUT_OF_MEMORY; } } retcode = parsenetrc(store, host, loginp, passwordp, filealloc); - free(filealloc); + curlx_free(filealloc); #ifdef _WIN32 if(retcode == NETRC_FILE_MISSING) { /* fallback to the old-style "_netrc" file */ filealloc = curl_maprintf("%s%s_netrc", home, DIR_CHAR); if(!filealloc) { - free(homea); + curlx_free(homea); return NETRC_OUT_OF_MEMORY; } retcode = parsenetrc(store, host, loginp, passwordp, filealloc); - free(filealloc); + curlx_free(filealloc); } #endif - free(homea); + curlx_free(homea); } else retcode = parsenetrc(store, host, loginp, passwordp, netrcfile); diff --git a/lib/netrc.h b/lib/netrc.h index 0d6d081bfbb9..af07c812a5d8 100644 --- a/lib/netrc.h +++ b/lib/netrc.h @@ -25,6 +25,7 @@ ***************************************************************************/ #include "curl_setup.h" + #ifndef CURL_DISABLE_NETRC #include "curlx/dynbuf.h" @@ -50,14 +51,14 @@ void Curl_netrc_cleanup(struct store_netrc *s); NETRCcode Curl_parsenetrc(struct store_netrc *s, const char *host, char **loginp, char **passwordp, const char *filename); - /* Assume: (*passwordp)[0]=0, host[0] != 0. - * If (*loginp)[0] = 0, search for login and password within a machine - * section in the netrc. - * If (*loginp)[0] != 0, search for password within machine and login. - */ +/* Assume: (*passwordp)[0]=0, host[0] != 0. + * If (*loginp)[0] = 0, search for login and password within a machine + * section in the netrc. + * If (*loginp)[0] != 0, search for password within machine and login. + */ #else /* disabled */ -#define Curl_parsenetrc(a,b,c,d,e,f) 1 +#define Curl_parsenetrc(a, b, c, d, e, f) 1 #define Curl_netrc_init(x) #define Curl_netrc_cleanup(x) #endif diff --git a/lib/noproxy.c b/lib/noproxy.c index 20a335993da1..5c0c58530deb 100644 --- a/lib/noproxy.c +++ b/lib/noproxy.c @@ -26,7 +26,6 @@ #ifndef CURL_DISABLE_PROXY -#include /* for curl_strnequal() */ #include "curlx/inet_pton.h" #include "noproxy.h" #include "curlx/strparse.h" @@ -117,14 +116,74 @@ enum nametype { TYPE_IPV6 }; +static bool match_host(const char *token, size_t tokenlen, + const char *name, size_t namelen) +{ + bool match = FALSE; + + /* ignore trailing dots in the token to check */ + if(token[tokenlen - 1] == '.') + tokenlen--; + + if(tokenlen && (*token == '.')) { + /* ignore leading token dot as well */ + token++; + tokenlen--; + } + /* A: example.com matches 'example.com' + B: www.example.com matches 'example.com' + C: nonexample.com DOES NOT match 'example.com' + */ + if(tokenlen == namelen) + /* case A, exact match */ + match = curl_strnequal(token, name, namelen); + else if(tokenlen < namelen) { + /* case B, tailmatch domain */ + match = (name[namelen - tokenlen - 1] == '.') && + curl_strnequal(token, name + (namelen - tokenlen), tokenlen); + } + /* case C passes through, not a match */ + return match; +} + +static bool match_ip(int type, const char *token, size_t tokenlen, + const char *name) +{ + const char *check = token; + char *slash; + unsigned int bits = 0; + char checkip[128]; + if(tokenlen >= sizeof(checkip)) + /* this cannot match */ + return FALSE; + /* copy the check name to a temp buffer */ + memcpy(checkip, check, tokenlen); + checkip[tokenlen] = 0; + check = checkip; + + slash = strchr(check, '/'); + /* if the slash is part of this token, use it */ + if(slash) { + curl_off_t value; + const char *p = &slash[1]; + if(curlx_str_number(&p, &value, 128) || *p) + return FALSE; + /* a too large value is rejected in the cidr function below */ + bits = (unsigned int)value; + *slash = 0; /* null-terminate there */ + } + if(type == TYPE_IPV6) + return Curl_cidr6_match(name, check, bits); + else + return Curl_cidr4_match(name, check, bits); +} + /**************************************************************** -* Checks if the host is in the noproxy list. returns TRUE if it matches and -* therefore the proxy should NOT be used. -****************************************************************/ + * Checks if the host is in the noproxy list. returns TRUE if it matches and + * therefore the proxy should NOT be used. + ****************************************************************/ bool Curl_check_noproxy(const char *name, const char *no_proxy) { - char hostip[128]; - /* * If we do not have a hostname at all, like for example with a FILE * transfer, we have nothing to interrogate the noproxy list with. @@ -140,43 +199,30 @@ bool Curl_check_noproxy(const char *name, const char *no_proxy) if(no_proxy && no_proxy[0]) { const char *p = no_proxy; size_t namelen; + char address[16]; enum nametype type = TYPE_HOST; if(!strcmp("*", no_proxy)) return TRUE; /* NO_PROXY was specified and it was not just an asterisk */ - if(name[0] == '[') { - char *endptr; - /* IPv6 numerical address */ - endptr = strchr(name, ']'); - if(!endptr) - return FALSE; - name++; - namelen = endptr - name; - if(namelen >= sizeof(hostip)) - return FALSE; - memcpy(hostip, name, namelen); - hostip[namelen] = 0; - name = hostip; + /* Check if name is an IP address; if not, assume it being a hostname. */ + namelen = strlen(name); + if(curlx_inet_pton(AF_INET, name, &address) == 1) + type = TYPE_IPV4; +#ifdef USE_IPV6 + else if(curlx_inet_pton(AF_INET6, name, &address) == 1) type = TYPE_IPV6; - } +#endif else { - unsigned int address; - namelen = strlen(name); - if(curlx_inet_pton(AF_INET, name, &address) == 1) - type = TYPE_IPV4; - else { - /* ignore trailing dots in the hostname */ - if(name[namelen - 1] == '.') - namelen--; - } + /* ignore trailing dots in the hostname */ + if(name[namelen - 1] == '.') + namelen--; } while(*p) { const char *token; size_t tokenlen = 0; - bool match = FALSE; /* pass blanks */ curlx_str_passblanks(&p); @@ -189,64 +235,16 @@ bool Curl_check_noproxy(const char *name, const char *no_proxy) } if(tokenlen) { - switch(type) { - case TYPE_HOST: - /* ignore trailing dots in the token to check */ - if(token[tokenlen - 1] == '.') - tokenlen--; - - if(tokenlen && (*token == '.')) { - /* ignore leading token dot as well */ - token++; - tokenlen--; - } - /* A: example.com matches 'example.com' - B: www.example.com matches 'example.com' - C: nonexample.com DOES NOT match 'example.com' - */ - if(tokenlen == namelen) - /* case A, exact match */ - match = curl_strnequal(token, name, namelen); - else if(tokenlen < namelen) { - /* case B, tailmatch domain */ - match = (name[namelen - tokenlen - 1] == '.') && - curl_strnequal(token, name + (namelen - tokenlen), - tokenlen); - } - /* case C passes through, not a match */ - break; - case TYPE_IPV4: - case TYPE_IPV6: { - const char *check = token; - char *slash; - unsigned int bits = 0; - char checkip[128]; - if(tokenlen >= sizeof(checkip)) - /* this cannot match */ - break; - /* copy the check name to a temp buffer */ - memcpy(checkip, check, tokenlen); - checkip[tokenlen] = 0; - check = checkip; + bool match = FALSE; + if(type == TYPE_HOST) + match = match_host(token, tokenlen, name, namelen); + else + match = match_ip(type, token, tokenlen, name); - slash = strchr(check, '/'); - /* if the slash is part of this token, use it */ - if(slash) { - /* if the bits variable gets a crazy value here, that is fine as - the value will then be rejected in the cidr function */ - bits = (unsigned int)atoi(slash + 1); - *slash = 0; /* null-terminate there */ - } - if(type == TYPE_IPV6) - match = Curl_cidr6_match(name, check, bits); - else - match = Curl_cidr4_match(name, check, bits); - break; - } - } if(match) return TRUE; - } /* if(tokenlen) */ + } + /* pass blanks after pattern */ curlx_str_passblanks(&p); /* if not a comma, this ends the loop */ diff --git a/lib/openldap.c b/lib/openldap.c index 1b26b6e1b4d9..e78080ab83f3 100644 --- a/lib/openldap.c +++ b/lib/openldap.c @@ -42,8 +42,8 @@ #include "urldata.h" #include "url.h" -#include #include "sendf.h" +#include "curl_trc.h" #include "vtls/vtls.h" #include "transfer.h" #include "curl_ldap.h" @@ -52,10 +52,7 @@ #include "connect.h" #include "curl_sasl.h" #include "strcase.h" - -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" +#include "bufref.h" /* * Uncommenting this will enable the built-in debug logging of the openldap @@ -116,7 +113,6 @@ static Curl_recv oldap_recv; /* * LDAP protocol handler. */ - const struct Curl_handler Curl_handler_ldap = { "ldap", /* scheme */ oldap_setup_connection, /* setup_connection */ @@ -139,14 +135,14 @@ const struct Curl_handler Curl_handler_ldap = { PORT_LDAP, /* defport */ CURLPROTO_LDAP, /* protocol */ CURLPROTO_LDAP, /* family */ - PROTOPT_SSL_REUSE /* flags */ + PROTOPT_SSL_REUSE | /* flags */ + PROTOPT_CONN_REUSE }; #ifdef USE_SSL /* * LDAPS protocol handler. */ - const struct Curl_handler Curl_handler_ldaps = { "ldaps", /* scheme */ oldap_setup_connection, /* setup_connection */ @@ -169,7 +165,8 @@ const struct Curl_handler Curl_handler_ldaps = { PORT_LDAPS, /* defport */ CURLPROTO_LDAPS, /* protocol */ CURLPROTO_LDAP, /* family */ - PROTOPT_SSL /* flags */ + PROTOPT_SSL | /* flags */ + PROTOPT_CONN_REUSE }; #endif @@ -276,14 +273,14 @@ static CURLcode oldap_url_parse(struct Curl_easy *data, LDAPURLDesc **ludp) *ludp = NULL; if(!data->state.up.user && !data->state.up.password && !data->state.up.options) - rc = ldap_url_parse(data->state.url, ludp); + rc = ldap_url_parse(Curl_bufref_ptr(&data->state.url), ludp); if(rc != LDAP_URL_SUCCESS) { const char *msg = "url parsing problem"; result = rc == LDAP_URL_ERR_MEM ? CURLE_OUT_OF_MEMORY : CURLE_URL_MALFORMAT; rc -= LDAP_URL_SUCCESS; - if((size_t) rc < CURL_ARRAYSIZE(url_errs)) + if((size_t)rc < CURL_ARRAYSIZE(url_errs)) msg = url_errs[rc]; failf(data, "LDAP local: %s", msg); } @@ -509,8 +506,7 @@ static ber_slen_t ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len); static int ldapsb_tls_close(Sockbuf_IO_Desc *sbiod); -static Sockbuf_IO ldapsb_tls = -{ +static Sockbuf_IO ldapsb_tls = { ldapsb_tls_setup, ldapsb_tls_remove, ldapsb_tls_ctrl, @@ -575,7 +571,7 @@ static void oldap_easy_dtor(void *key, size_t klen, void *entry) struct ldapreqinfo *lr = entry; (void)key; (void)klen; - free(lr); + curlx_free(lr); } static void oldap_conn_dtor(void *key, size_t klen, void *entry) @@ -587,7 +583,7 @@ static void oldap_conn_dtor(void *key, size_t klen, void *entry) ldap_unbind_ext(li->ld, NULL, NULL); li->ld = NULL; } - free(li); + curlx_free(li); } static CURLcode oldap_connect(struct Curl_easy *data, bool *done) @@ -604,7 +600,7 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done) (void)done; - li = calloc(1, sizeof(struct ldapconninfo)); + li = curlx_calloc(1, sizeof(struct ldapconninfo)); if(!li) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -660,13 +656,13 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done) ldap_set_option(li->ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF); { - ber_len_t max = 256*1024; + ber_len_t max = 256 * 1024; Sockbuf *sb; - if(ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, (void **)&sb) || + if((ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb) != LDAP_OPT_SUCCESS) || /* Set the maximum allowed size of an incoming message, which to OpenLDAP means that it will malloc() memory up to this size. If not set, there is no limit and we instead risk a malloc() failure. */ - ber_sockbuf_ctrl(sb, LBER_SB_OPT_SET_MAX_INCOMING, &max)) { + !ber_sockbuf_ctrl(sb, LBER_SB_OPT_SET_MAX_INCOMING, &max)) { result = CURLE_FAILED_INIT; goto out; } @@ -695,7 +691,7 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done) result = oldap_perform_bind(data, OLDAP_BIND); out: - free(hosturl); + curlx_free(hosturl); return result; } @@ -732,7 +728,7 @@ static CURLcode oldap_state_mechs_resp(struct Curl_easy *data, if(bvals) { for(i = 0; bvals[i].bv_val; i++) { size_t llen; - unsigned short mech = Curl_sasl_decode_mech((char *) bvals[i].bv_val, + unsigned short mech = Curl_sasl_decode_mech((char *)bvals[i].bv_val, bvals[i].bv_len, &llen); if(bvals[i].bv_len == llen) li->sasl.authmechs |= mech; @@ -746,7 +742,7 @@ static CURLcode oldap_state_mechs_resp(struct Curl_easy *data, case LDAP_RES_SEARCH_RESULT: switch(code) { case LDAP_SIZELIMIT_EXCEEDED: - infof(data, "Too many authentication mechanisms\n"); + infof(data, "Too many authentication mechanisms"); FALLTHROUGH(); case LDAP_SUCCESS: case LDAP_NO_RESULTS_RETURNED: @@ -831,7 +827,7 @@ static CURLcode oldap_connecting(struct Curl_easy *data, bool *done) struct connectdata *conn = data->conn; struct ldapconninfo *li = Curl_conn_meta_get(conn, CURL_META_LDAP_CONN); LDAPMessage *msg = NULL; - struct timeval tv = {0, 0}; + struct timeval tv = { 0, 0 }; int code = LDAP_SUCCESS; int rc; @@ -992,9 +988,8 @@ static CURLcode oldap_do(struct Curl_easy *data, bool *done) if(!li) return CURLE_FAILED_INIT; - connkeep(conn, "OpenLDAP do"); - infof(data, "LDAP local: %s", data->state.url); + infof(data, "LDAP local: %s", Curl_bufref_ptr(&data->state.url)); result = oldap_url_parse(data, &lud); if(result) @@ -1022,7 +1017,7 @@ static CURLcode oldap_do(struct Curl_easy *data, bool *done) goto out; } - lr = calloc(1, sizeof(struct ldapreqinfo)); + lr = curlx_calloc(1, sizeof(struct ldapreqinfo)); if(!lr || Curl_meta_set(data, CURL_META_LDAP_EASY, lr, oldap_easy_dtor)) { ldap_abandon_ext(li->ld, msgid, NULL, NULL); @@ -1094,9 +1089,8 @@ static CURLcode oldap_recv(struct Curl_easy *data, int sockindex, char *buf, int rc; LDAPMessage *msg = NULL; BerElement *ber = NULL; - struct timeval tv = {0, 0}; + struct timeval tv = { 0, 0 }; struct berval bv, *bvals; - bool binary = FALSE; CURLcode result = CURLE_AGAIN; int code; char *info = NULL; @@ -1167,6 +1161,7 @@ static CURLcode oldap_recv(struct Curl_easy *data, int sockindex, char *buf, rc == LDAP_SUCCESS; rc = ldap_get_attribute_ber(li->ld, msg, ber, &bv, &bvals)) { int i; + bool binary; if(!bv.bv_val) break; @@ -1180,7 +1175,7 @@ static CURLcode oldap_recv(struct Curl_easy *data, int sockindex, char *buf, } binary = bv.bv_len > 7 && - !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7); + curl_strnequal(bv.bv_val + bv.bv_len - 7, ";binary", 7); for(i = 0; bvals[i].bv_val != NULL; i++) { bool binval = FALSE; @@ -1212,12 +1207,13 @@ static CURLcode oldap_recv(struct Curl_easy *data, int sockindex, char *buf, /* Binary value, encode to base64. */ if(bvals[i].bv_len) - result = curlx_base64_encode(bvals[i].bv_val, bvals[i].bv_len, + result = curlx_base64_encode((uint8_t *)bvals[i].bv_val, + bvals[i].bv_len, &val_b64, &val_b64_sz); if(!result) result = client_write(data, STRCONST(": "), val_b64, val_b64_sz, STRCONST("\n")); - free(val_b64); + curlx_free(val_b64); } else result = client_write(data, STRCONST(" "), @@ -1235,7 +1231,6 @@ static CURLcode oldap_recv(struct Curl_easy *data, int sockindex, char *buf, break; } - if(!result) result = client_write(data, STRCONST("\n"), NULL, 0, NULL, 0); if(!result) @@ -1249,30 +1244,26 @@ static CURLcode oldap_recv(struct Curl_easy *data, int sockindex, char *buf, } #ifdef USE_SSL -static int -ldapsb_tls_setup(Sockbuf_IO_Desc *sbiod, void *arg) +static int ldapsb_tls_setup(Sockbuf_IO_Desc *sbiod, void *arg) { sbiod->sbiod_pvt = arg; return 0; } -static int -ldapsb_tls_remove(Sockbuf_IO_Desc *sbiod) +static int ldapsb_tls_remove(Sockbuf_IO_Desc *sbiod) { sbiod->sbiod_pvt = NULL; return 0; } /* We do not need to do anything because libcurl does it already */ -static int -ldapsb_tls_close(Sockbuf_IO_Desc *sbiod) +static int ldapsb_tls_close(Sockbuf_IO_Desc *sbiod) { (void)sbiod; return 0; } -static int -ldapsb_tls_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg) +static int ldapsb_tls_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg) { (void)arg; if(opt == LBER_SB_OPT_DATA_READY) { @@ -1282,8 +1273,8 @@ ldapsb_tls_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg) return 0; } -static ber_slen_t -ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) +static ber_slen_t ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, + ber_len_t len) { struct Curl_easy *data = sbiod->sbiod_pvt; ber_slen_t ret = 0; @@ -1307,8 +1298,8 @@ ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) } return ret; } -static ber_slen_t -ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) +static ber_slen_t ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, + ber_len_t len) { struct Curl_easy *data = sbiod->sbiod_pvt; ber_slen_t ret = 0; @@ -1334,4 +1325,24 @@ ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len) } #endif /* USE_SSL */ +void Curl_ldap_version(char *buf, size_t bufsz) +{ + LDAPAPIInfo api; + api.ldapai_info_version = LDAP_API_INFO_VERSION; + + if(ldap_get_option(NULL, LDAP_OPT_API_INFO, &api) == LDAP_OPT_SUCCESS) { + unsigned int patch = (unsigned int)(api.ldapai_vendor_version % 100); + unsigned int major = (unsigned int)(api.ldapai_vendor_version / 10000); + unsigned int minor = + (((unsigned int)api.ldapai_vendor_version - major * 10000) + - patch) / 100; + curl_msnprintf(buf, bufsz, "%s/%u.%u.%u", + api.ldapai_vendor_name, major, minor, patch); + ldap_memfree(api.ldapai_vendor_name); + ber_memvfree((void **)api.ldapai_extensions); + } + else + curl_msnprintf(buf, bufsz, "OpenLDAP"); +} + #endif /* !CURL_DISABLE_LDAP && USE_OPENLDAP */ diff --git a/lib/optiontable.pl b/lib/optiontable.pl index 43fbd39d3bfc..1222536794a8 100755 --- a/lib/optiontable.pl +++ b/lib/optiontable.pl @@ -31,6 +31,7 @@ /* This source code is generated by optiontable.pl - DO NOT EDIT BY HAND */ #include "curl_setup.h" + #include "easyoptions.h" /* all easy setopt options listed in alphabetical order */ @@ -77,7 +78,6 @@ sub add { } } - my $fl; while() { my $l = $_; @@ -122,7 +122,6 @@ sub add { } } - for my $name (sort @names) { my $oname = $name; my $a = $alias{$name}; @@ -131,19 +130,19 @@ sub add { $name = $alias{$name}; $flag = "CURLOT_FLAG_ALIAS"; } - my $o = sprintf(" {\"%s\", %s, %s, %s},\n", + my $o = sprintf(" { \"%s\", %s, %s, %s },\n", $oname, $opt{$name}, $type{$name}, $flag); if(length($o) < 80) { print $o; } else { - printf(" {\"%s\", %s,\n %s, %s},\n", - $oname, $opt{$name}, $type{$name}, $flag); + printf(" { \"%s\", %s,\n %s, %s },\n", + $oname, $opt{$name}, $type{$name}, $flag); } } print < - -#include -#include "curlx/warnless.h" #include "parsedate.h" #include "curlx/strparse.h" @@ -107,17 +103,19 @@ static int parsedate(const char *date, time_t *output); #if !defined(CURL_DISABLE_PARSEDATE) || !defined(CURL_DISABLE_FTP) || \ !defined(CURL_DISABLE_FILE) || defined(USE_GNUTLS) /* These names are also used by FTP and FILE code */ -const char * const Curl_wkday[] = -{"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; -const char * const Curl_month[]= -{ "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; +const char * const Curl_wkday[] = { + "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" +}; +const char * const Curl_month[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; #endif #ifndef CURL_DISABLE_PARSEDATE -static const char * const weekday[] = -{ "Monday", "Tuesday", "Wednesday", "Thursday", - "Friday", "Saturday", "Sunday" }; +static const char * const weekday[] = { + "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" +}; struct tzinfo { char name[5]; @@ -127,83 +125,83 @@ struct tzinfo { /* Here's a bunch of frequently used time zone names. These were supported by the old getdate parser. */ #define tDAYZONE -60 /* offset for daylight savings time */ -static const struct tzinfo tz[]= { - {"GMT", 0}, /* Greenwich Mean */ - {"UT", 0}, /* Universal Time */ - {"UTC", 0}, /* Universal (Coordinated) */ - {"WET", 0}, /* Western European */ - {"BST", 0 tDAYZONE}, /* British Summer */ - {"WAT", 60}, /* West Africa */ - {"AST", 240}, /* Atlantic Standard */ - {"ADT", 240 tDAYZONE}, /* Atlantic Daylight */ - {"EST", 300}, /* Eastern Standard */ - {"EDT", 300 tDAYZONE}, /* Eastern Daylight */ - {"CST", 360}, /* Central Standard */ - {"CDT", 360 tDAYZONE}, /* Central Daylight */ - {"MST", 420}, /* Mountain Standard */ - {"MDT", 420 tDAYZONE}, /* Mountain Daylight */ - {"PST", 480}, /* Pacific Standard */ - {"PDT", 480 tDAYZONE}, /* Pacific Daylight */ - {"YST", 540}, /* Yukon Standard */ - {"YDT", 540 tDAYZONE}, /* Yukon Daylight */ - {"HST", 600}, /* Hawaii Standard */ - {"HDT", 600 tDAYZONE}, /* Hawaii Daylight */ - {"CAT", 600}, /* Central Alaska */ - {"AHST", 600}, /* Alaska-Hawaii Standard */ - {"NT", 660}, /* Nome */ /* spellchecker:disable-line */ - {"IDLW", 720}, /* International Date Line West */ - {"CET", -60}, /* Central European */ - {"MET", -60}, /* Middle European */ - {"MEWT", -60}, /* Middle European Winter */ - {"MEST", -60 tDAYZONE}, /* Middle European Summer */ - {"CEST", -60 tDAYZONE}, /* Central European Summer */ - {"MESZ", -60 tDAYZONE}, /* Middle European Summer */ - {"FWT", -60}, /* French Winter */ - {"FST", -60 tDAYZONE}, /* French Summer */ - {"EET", -120}, /* Eastern Europe, USSR Zone 1 */ - {"WAST", -420}, /* spellchecker:disable-line */ - /* West Australian Standard */ - {"WADT", -420 tDAYZONE}, /* West Australian Daylight */ - {"CCT", -480}, /* China Coast, USSR Zone 7 */ - {"JST", -540}, /* Japan Standard, USSR Zone 8 */ - {"EAST", -600}, /* Eastern Australian Standard */ - {"EADT", -600 tDAYZONE}, /* Eastern Australian Daylight */ - {"GST", -600}, /* Guam Standard, USSR Zone 9 */ - {"NZT", -720}, /* New Zealand */ - {"NZST", -720}, /* New Zealand Standard */ - {"NZDT", -720 tDAYZONE}, /* New Zealand Daylight */ - {"IDLE", -720}, /* International Date Line East */ +static const struct tzinfo tz[] = { + { "GMT", 0 }, /* Greenwich Mean */ + { "UT", 0 }, /* Universal Time */ + { "UTC", 0 }, /* Universal (Coordinated) */ + { "WET", 0 }, /* Western European */ + { "BST", 0 tDAYZONE }, /* British Summer */ + { "WAT", 60 }, /* West Africa */ + { "AST", 240 }, /* Atlantic Standard */ + { "ADT", 240 tDAYZONE }, /* Atlantic Daylight */ + { "EST", 300 }, /* Eastern Standard */ + { "EDT", 300 tDAYZONE }, /* Eastern Daylight */ + { "CST", 360 }, /* Central Standard */ + { "CDT", 360 tDAYZONE }, /* Central Daylight */ + { "MST", 420 }, /* Mountain Standard */ + { "MDT", 420 tDAYZONE }, /* Mountain Daylight */ + { "PST", 480 }, /* Pacific Standard */ + { "PDT", 480 tDAYZONE }, /* Pacific Daylight */ + { "YST", 540 }, /* Yukon Standard */ + { "YDT", 540 tDAYZONE }, /* Yukon Daylight */ + { "HST", 600 }, /* Hawaii Standard */ + { "HDT", 600 tDAYZONE }, /* Hawaii Daylight */ + { "CAT", 600 }, /* Central Alaska */ + { "AHST", 600 }, /* Alaska-Hawaii Standard */ + { "NT", 660 }, /* Nome */ /* spellchecker:disable-line */ + { "IDLW", 720 }, /* International Date Line West */ + { "CET", -60 }, /* Central European */ + { "MET", -60 }, /* Middle European */ + { "MEWT", -60 }, /* Middle European Winter */ + { "MEST", -60 tDAYZONE }, /* Middle European Summer */ + { "CEST", -60 tDAYZONE }, /* Central European Summer */ + { "MESZ", -60 tDAYZONE }, /* Middle European Summer */ + { "FWT", -60 }, /* French Winter */ + { "FST", -60 tDAYZONE }, /* French Summer */ + { "EET", -120 }, /* Eastern Europe, USSR Zone 1 */ + { "WAST", -420 }, /* spellchecker:disable-line */ + /* West Australian Standard */ + { "WADT", -420 tDAYZONE }, /* West Australian Daylight */ + { "CCT", -480 }, /* China Coast, USSR Zone 7 */ + { "JST", -540 }, /* Japan Standard, USSR Zone 8 */ + { "EAST", -600 }, /* Eastern Australian Standard */ + { "EADT", -600 tDAYZONE }, /* Eastern Australian Daylight */ + { "GST", -600 }, /* Guam Standard, USSR Zone 9 */ + { "NZT", -720 }, /* New Zealand */ + { "NZST", -720 }, /* New Zealand Standard */ + { "NZDT", -720 tDAYZONE }, /* New Zealand Daylight */ + { "IDLE", -720 }, /* International Date Line East */ /* Next up: Military timezone names. RFC822 allowed these, but (as noted in RFC 1123) had their signs wrong. Here we use the correct signs to match actual military usage. */ - {"A", 1 * 60}, /* Alpha */ - {"B", 2 * 60}, /* Bravo */ - {"C", 3 * 60}, /* Charlie */ - {"D", 4 * 60}, /* Delta */ - {"E", 5 * 60}, /* Echo */ - {"F", 6 * 60}, /* Foxtrot */ - {"G", 7 * 60}, /* Golf */ - {"H", 8 * 60}, /* Hotel */ - {"I", 9 * 60}, /* India */ + { "A", 1 * 60 }, /* Alpha */ + { "B", 2 * 60 }, /* Bravo */ + { "C", 3 * 60 }, /* Charlie */ + { "D", 4 * 60 }, /* Delta */ + { "E", 5 * 60 }, /* Echo */ + { "F", 6 * 60 }, /* Foxtrot */ + { "G", 7 * 60 }, /* Golf */ + { "H", 8 * 60 }, /* Hotel */ + { "I", 9 * 60 }, /* India */ /* "J", Juliet is not used as a timezone, to indicate the observer's local time */ - {"K", 10 * 60}, /* Kilo */ - {"L", 11 * 60}, /* Lima */ - {"M", 12 * 60}, /* Mike */ - {"N", -1 * 60}, /* November */ - {"O", -2 * 60}, /* Oscar */ - {"P", -3 * 60}, /* Papa */ - {"Q", -4 * 60}, /* Quebec */ - {"R", -5 * 60}, /* Romeo */ - {"S", -6 * 60}, /* Sierra */ - {"T", -7 * 60}, /* Tango */ - {"U", -8 * 60}, /* Uniform */ - {"V", -9 * 60}, /* Victor */ - {"W", -10 * 60}, /* Whiskey */ - {"X", -11 * 60}, /* X-ray */ - {"Y", -12 * 60}, /* Yankee */ - {"Z", 0}, /* Zulu, zero meridian, a.k.a. UTC */ + { "K", 10 * 60 }, /* Kilo */ + { "L", 11 * 60 }, /* Lima */ + { "M", 12 * 60 }, /* Mike */ + { "N", -1 * 60 }, /* November */ + { "O", -2 * 60 }, /* Oscar */ + { "P", -3 * 60 }, /* Papa */ + { "Q", -4 * 60 }, /* Quebec */ + { "R", -5 * 60 }, /* Romeo */ + { "S", -6 * 60 }, /* Sierra */ + { "T", -7 * 60 }, /* Tango */ + { "U", -8 * 60 }, /* Uniform */ + { "V", -9 * 60 }, /* Victor */ + { "W", -10 * 60 }, /* Whiskey */ + { "X", -11 * 60 }, /* X-ray */ + { "Y", -12 * 60 }, /* Yankee */ + { "Z", 0 }, /* Zulu, zero meridian, a.k.a. UTC */ }; /* returns: @@ -260,7 +258,7 @@ static int checktz(const char *check, size_t len) size_t ilen = strlen(what->name); if((ilen == len) && curl_strnequal(check, what->name, len)) - return what->offset*60; + return what->offset * 60; what++; } return -1; @@ -286,12 +284,13 @@ enum assume { static time_t time2epoch(int sec, int min, int hour, int mday, int mon, int year) { - static const int month_days_cumulative [12] = - { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; + static const int month_days_cumulative[12] = { + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 + }; int leap_days = year - (mon <= 1); leap_days = ((leap_days / 4) - (leap_days / 100) + (leap_days / 400) - (1969 / 4) + (1969 / 100) - (1969 / 400)); - return ((((time_t) (year - 1970) * 365 + return ((((time_t)(year - 1970) * 365 + leap_days + month_days_cumulative[mon] + mday - 1) * 24 + hour) * 60 + min) * 60 + sec; } @@ -304,13 +303,12 @@ static int oneortwodigit(const char *date, const char **endp) int num = date[0] - '0'; if(ISDIGIT(date[1])) { *endp = &date[2]; - return num*10 + (date[1] - '0'); + return num * 10 + (date[1] - '0'); } *endp = &date[1]; return num; } - /* HH:MM:SS or HH:MM and accept single-digits too */ static bool match_time(const char *date, int *h, int *m, int *s, char **endp) @@ -362,7 +360,7 @@ static int parsedate(const char *date, time_t *output) time_t t = 0; int wdaynum = -1; /* day of the week number, 0-6 (mon-sun) */ int monnum = -1; /* month of the year number, 0-11 */ - int mdaynum = -1; /* day of month, 1 - 31 */ + int mdaynum = -1; /* day of month, 1 - 31 */ int hournum = -1; int minnum = -1; int secnum = -1; @@ -444,11 +442,11 @@ static int parsedate(const char *date, time_t *output) anyone has a more authoritative source for the exact maximum time zone offsets, please speak up! */ found = TRUE; - tzoff = (val/100 * 60 + val%100)*60; + tzoff = (val / 100 * 60 + val % 100) * 60; /* the + and - prefix indicates the local time compared to GMT, this we need their reversed math to get what we want */ - tzoff = date[-1]=='+' ? -tzoff : tzoff; + tzoff = date[-1] == '+' ? -tzoff : tzoff; } else if((num_digits == 8) && @@ -457,9 +455,9 @@ static int parsedate(const char *date, time_t *output) (mdaynum == -1)) { /* 8 digits, no year, month or day yet. This is YYYYMMDD */ found = TRUE; - yearnum = val/10000; - monnum = (val%10000)/100-1; /* month is 0 - 11 */ - mdaynum = val%100; + yearnum = val / 10000; + monnum = (val % 10000) / 100 - 1; /* month is 0 - 11 */ + mdaynum = val % 100; } if(!found && (dignext == DATE_MDAY) && (mdaynum == -1)) { @@ -596,27 +594,3 @@ int Curl_getdate_capped(const char *p, time_t *tp) int rc = parsedate(p, tp); return (rc == PARSEDATE_FAIL); } - -/* - * Curl_gmtime() is a gmtime() replacement for portability. Do not use the - * gmtime_r() or gmtime() functions anywhere else but here. - * - */ - -CURLcode Curl_gmtime(time_t intime, struct tm *store) -{ - const struct tm *tm; -#ifdef HAVE_GMTIME_R - /* thread-safe version */ - tm = (struct tm *)gmtime_r(&intime, store); -#else - /* !checksrc! disable BANNEDFUNC 1 */ - tm = gmtime(&intime); - if(tm) - *store = *tm; /* copy the pointed struct to the local copy */ -#endif - - if(!tm) - return CURLE_BAD_FUNCTION_ARGUMENT; - return CURLE_OK; -} diff --git a/lib/parsedate.h b/lib/parsedate.h index e5efb53f617d..ef2578098d5f 100644 --- a/lib/parsedate.h +++ b/lib/parsedate.h @@ -27,8 +27,6 @@ extern const char * const Curl_wkday[7]; extern const char * const Curl_month[12]; -CURLcode Curl_gmtime(time_t intime, struct tm *store); - /* Curl_getdate_capped() differs from curl_getdate() in that this returns TIME_T_MAX in case the parsed time value was too big, instead of an error. */ diff --git a/lib/pingpong.c b/lib/pingpong.c index 3f6da71eae2c..8c5cf05fc219 100644 --- a/lib/pingpong.c +++ b/lib/pingpong.c @@ -31,17 +31,10 @@ #include "cfilters.h" #include "connect.h" #include "sendf.h" +#include "curl_trc.h" #include "select.h" #include "progress.h" -#include "speedcheck.h" #include "pingpong.h" -#include "multiif.h" -#include "vtls/vtls.h" -#include "strdup.h" - -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" #ifdef USE_PINGPONG @@ -51,9 +44,8 @@ timediff_t Curl_pp_state_timeout(struct Curl_easy *data, struct pingpong *pp, bool disconnecting) { timediff_t timeout_ms; /* in milliseconds */ - timediff_t response_time = (data->set.server_response_timeout > 0) ? - data->set.server_response_timeout : pp->response_time; - struct curltime now = curlx_now(); + timediff_t response_time = data->set.server_response_timeout ? + data->set.server_response_timeout : RESP_TIMEOUT; /* if CURLOPT_SERVER_RESPONSE_TIMEOUT is set, use that to determine remaining time, or use pp->response because SERVER_RESPONSE_TIMEOUT is @@ -62,17 +54,18 @@ timediff_t Curl_pp_state_timeout(struct Curl_easy *data, /* Without a requested timeout, we only wait 'response_time' seconds for the full response to arrive before we bail out */ - timeout_ms = response_time - curlx_timediff(now, pp->response); + timeout_ms = response_time - + curlx_ptimediff_ms(Curl_pgrs_now(data), &pp->response); - if((data->set.timeout > 0) && !disconnecting) { + if(data->set.timeout && !disconnecting) { /* if timeout is requested, find out how much overall remains */ - timediff_t timeout2_ms = Curl_timeleft(data, &now, FALSE); + timediff_t timeout2_ms = Curl_timeleft_ms(data, FALSE); /* pick the lowest number */ timeout_ms = CURLMIN(timeout_ms, timeout2_ms); } if(disconnecting) { - timediff_t total_left_ms = Curl_timeleft(data, NULL, FALSE); + timediff_t total_left_ms = Curl_timeleft_ms(data, FALSE); timeout_ms = CURLMIN(timeout_ms, CURLMAX(total_left_ms, 0)); } @@ -123,11 +116,7 @@ CURLcode Curl_pp_statemach(struct Curl_easy *data, if(block) { /* if we did not wait, we do not have to spend time on this now */ - if(Curl_pgrsUpdate(data)) - result = CURLE_ABORTED_BY_CALLBACK; - else - result = Curl_speedcheck(data, curlx_now()); - + result = Curl_pgrsCheck(data); if(result) return result; } @@ -145,11 +134,11 @@ CURLcode Curl_pp_statemach(struct Curl_easy *data, } /* initialize stuff to prepare for reading a fresh new response */ -void Curl_pp_init(struct pingpong *pp) +void Curl_pp_init(struct pingpong *pp, const struct curltime *pnow) { DEBUGASSERT(!pp->initialised); pp->nread_resp = 0; - pp->response = curlx_now(); /* start response time-out now! */ + pp->response = *pnow; /* start response time-out */ pp->pending_resp = TRUE; curlx_dyn_init(&pp->sendbuf, DYN_PINGPPONG_CMD); curlx_dyn_init(&pp->recvbuf, DYN_PINGPPONG_CMD); @@ -218,13 +207,12 @@ CURLcode Curl_pp_vsendf(struct Curl_easy *data, else { pp->sendthis = NULL; pp->sendleft = pp->sendsize = 0; - pp->response = curlx_now(); + pp->response = *Curl_pgrs_now(data); } return CURLE_OK; } - /*********************************************************************** * * Curl_pp_sendf() @@ -285,7 +273,7 @@ CURLcode Curl_pp_readresp(struct Curl_easy *data, size_t full = curlx_dyn_len(&pp->recvbuf); /* trim off the "final" leading part */ - curlx_dyn_tail(&pp->recvbuf, full - pp->nfinal); + curlx_dyn_tail(&pp->recvbuf, full - pp->nfinal); pp->nfinal = 0; /* now gone */ } @@ -410,7 +398,7 @@ CURLcode Curl_pp_flushsend(struct Curl_easy *data, else { pp->sendthis = NULL; pp->sendleft = pp->sendsize = 0; - pp->response = curlx_now(); + pp->response = *Curl_pgrs_now(data); } return CURLE_OK; } diff --git a/lib/pingpong.h b/lib/pingpong.h index 5db96c4345f8..b3780571c480 100644 --- a/lib/pingpong.h +++ b/lib/pingpong.h @@ -53,8 +53,6 @@ struct pingpong { size_t sendsize; /* total size of the sendthis buffer */ struct curltime response; /* set to Curl_now() when a command has been sent off, used to time-out response reading */ - 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 */ @@ -73,11 +71,10 @@ struct pingpong { read */ }; -#define PINGPONG_SETUP(pp,s,e) \ - do { \ - (pp)->response_time = RESP_TIMEOUT; \ - (pp)->statemachine = s; \ - (pp)->endofresp = e; \ +#define PINGPONG_SETUP(pp, s, e) \ + do { \ + (pp)->statemachine = s; \ + (pp)->endofresp = e; \ } while(0) /* @@ -90,14 +87,13 @@ 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 pingpong *pp); +void Curl_pp_init(struct pingpong *pp, const struct curltime *pnow); /* Returns timeout in ms. 0 or negative number means the timeout has already triggered */ timediff_t Curl_pp_state_timeout(struct Curl_easy *data, struct pingpong *pp, bool disconnecting); - /*********************************************************************** * * Curl_pp_sendf() @@ -151,7 +147,6 @@ CURLcode Curl_pp_pollset(struct Curl_easy *data, struct pingpong *pp, struct easy_pollset *ps); - /*********************************************************************** * * Curl_pp_moredata() diff --git a/lib/pop3.c b/lib/pop3.c index 2fd496cb3142..f0216db25a52 100644 --- a/lib/pop3.c +++ b/lib/pop3.c @@ -55,44 +55,37 @@ #include #endif -#include #include "urldata.h" #include "sendf.h" +#include "curl_trc.h" #include "hostip.h" #include "progress.h" #include "transfer.h" #include "escape.h" #include "http.h" /* for HTTP proxy tunnel stuff */ -#include "socks.h" #include "pingpong.h" #include "pop3.h" #include "vtls/vtls.h" #include "cfilters.h" #include "connect.h" #include "select.h" -#include "multiif.h" #include "url.h" #include "bufref.h" #include "curl_sasl.h" #include "curl_md5.h" -#include "curlx/warnless.h" #include "strdup.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - /* Authentication type flags */ #define POP3_TYPE_CLEARTEXT (1 << 0) #define POP3_TYPE_APOP (1 << 1) #define POP3_TYPE_SASL (1 << 2) /* Authentication type values */ -#define POP3_TYPE_NONE 0 -#define POP3_TYPE_ANY (POP3_TYPE_CLEARTEXT|POP3_TYPE_APOP|POP3_TYPE_SASL) +#define POP3_TYPE_NONE 0 +#define POP3_TYPE_ANY (POP3_TYPE_CLEARTEXT | POP3_TYPE_APOP | POP3_TYPE_SASL) /* This is the 5-bytes End-Of-Body marker for POP3 */ -#define POP3_EOB "\x0d\x0a\x2e\x0d\x0a" +#define POP3_EOB "\x0d\x0a\x2e\x0d\x0a" #define POP3_EOB_LEN 5 /* meta key for storing protocol meta at easy handle */ @@ -200,7 +193,7 @@ const struct Curl_handler Curl_handler_pop3 = { CURLPROTO_POP3, /* protocol */ CURLPROTO_POP3, /* family */ PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */ - PROTOPT_URLOPTIONS | PROTOPT_SSL_REUSE + PROTOPT_URLOPTIONS | PROTOPT_SSL_REUSE | PROTOPT_CONN_REUSE }; #ifdef USE_SSL @@ -230,8 +223,8 @@ const struct Curl_handler Curl_handler_pop3s = { PORT_POP3S, /* defport */ CURLPROTO_POP3S, /* protocol */ CURLPROTO_POP3, /* family */ - PROTOPT_CLOSEACTION | PROTOPT_SSL - | PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS /* flags */ + PROTOPT_CLOSEACTION | PROTOPT_SSL | /* flags */ + PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS | PROTOPT_CONN_REUSE }; #endif @@ -323,8 +316,10 @@ static bool pop3_endofresp(struct Curl_easy *data, struct connectdata *conn, /* Are we processing CAPA command responses? */ if(pop3c->state == POP3_CAPA) { - /* Do we have the terminating line? */ - if(len >= 1 && line[0] == '.') + /* Do we have the terminating line? Per RFC 2449 this is a line + containing only a single dot */ + if((len == 3 && line[0] == '.' && line[1] == '\r') || + (len == 2 && line[0] == '.' && line[1] == '\n')) /* Treat the response as a success */ *resp = '+'; else @@ -512,7 +507,7 @@ static CURLcode pop3_perform_upgrade_tls(struct Curl_easy *data, result, ssldone)); if(!result && ssldone) { pop3c->ssldone = ssldone; - /* perform CAPA now, changes pop3c->state out of POP3_UPGRADETLS */ + /* perform CAPA now, changes pop3c->state out of POP3_UPGRADETLS */ result = pop3_perform_capa(data, conn); } out: @@ -589,10 +584,10 @@ static CURLcode pop3_perform_apop(struct Curl_easy *data, if(!ctxt) return CURLE_OUT_OF_MEMORY; - Curl_MD5_update(ctxt, (const unsigned char *) pop3c->apoptimestamp, + Curl_MD5_update(ctxt, (const unsigned char *)pop3c->apoptimestamp, curlx_uztoui(strlen(pop3c->apoptimestamp))); - Curl_MD5_update(ctxt, (const unsigned char *) conn->passwd, + Curl_MD5_update(ctxt, (const unsigned char *)conn->passwd, curlx_uztoui(strlen(conn->passwd))); /* Finalise the digest */ @@ -625,7 +620,7 @@ static CURLcode pop3_perform_auth(struct Curl_easy *data, struct pop3_conn *pop3c = Curl_conn_meta_get(data->conn, CURL_META_POP3_CONN); CURLcode result = CURLE_OK; - const char *ir = (const char *) Curl_bufref_ptr(initresp); + const char *ir = Curl_bufref_ptr(initresp); if(!pop3c) return CURLE_FAILED_INIT; @@ -659,8 +654,7 @@ static CURLcode pop3_continue_auth(struct Curl_easy *data, if(!pop3c) return CURLE_FAILED_INIT; - return Curl_pp_sendf(data, &pop3c->pp, - "%s", (const char *) Curl_bufref_ptr(resp)); + return Curl_pp_sendf(data, &pop3c->pp, "%s", Curl_bufref_ptr(resp)); } /*********************************************************************** @@ -876,15 +870,15 @@ static CURLcode pop3_state_capa_resp(struct Curl_easy *data, int pop3code, /* Do we have an untagged continuation response? */ if(pop3code == '*') { /* Does the server support the STLS capability? */ - if(len >= 4 && !memcmp(line, "STLS", 4)) + if(len >= 4 && curl_strnequal(line, "STLS", 4)) pop3c->tls_supported = TRUE; /* Does the server support clear text authentication? */ - else if(len >= 4 && !memcmp(line, "USER", 4)) + else if(len >= 4 && curl_strnequal(line, "USER", 4)) pop3c->authtypes |= POP3_TYPE_CLEARTEXT; /* Does the server support SASL based authentication? */ - else if(len >= 5 && !memcmp(line, "SASL ", 5)) { + else if(len >= 5 && curl_strnequal(line, "SASL ", 5)) { pop3c->authtypes |= POP3_TYPE_SASL; /* Advance past the SASL keyword */ @@ -894,13 +888,10 @@ static CURLcode pop3_state_capa_resp(struct Curl_easy *data, int pop3code, /* Loop through the data line */ for(;;) { size_t llen; - size_t wordlen; + size_t wordlen = 0; unsigned short mechbit; - while(len && - (*line == ' ' || *line == '\t' || - *line == '\r' || *line == '\n')) { - + while(len && (ISBLANK(*line) || ISNEWLINE(*line))) { line++; len--; } @@ -909,9 +900,8 @@ static CURLcode pop3_state_capa_resp(struct Curl_easy *data, int pop3code, break; /* Extract the word */ - for(wordlen = 0; wordlen < len && line[wordlen] != ' ' && - line[wordlen] != '\t' && line[wordlen] != '\r' && - line[wordlen] != '\n';) + while(wordlen < len && !ISBLANK(line[wordlen]) && + !ISNEWLINE(line[wordlen])) wordlen++; /* Test the word for a matching authentication mechanism */ @@ -1297,9 +1287,6 @@ static CURLcode pop3_connect(struct Curl_easy *data, bool *done) if(!pop3c) return CURLE_FAILED_INIT; - /* We always support persistent connections in POP3 */ - connkeep(conn, "POP3 default"); - PINGPONG_SETUP(pp, pop3_statemachine, pop3_endofresp); /* Set the default preferred authentication type and mechanism */ @@ -1307,7 +1294,7 @@ static CURLcode pop3_connect(struct Curl_easy *data, bool *done) Curl_sasl_init(&pop3c->sasl, data, &saslpop3); /* Initialise the pingpong layer */ - Curl_pp_init(pp); + Curl_pp_init(pp, Curl_pgrs_now(data)); /* Parse the URL options */ result = pop3_parse_url_options(conn); @@ -1505,10 +1492,7 @@ static CURLcode pop3_regular_transfer(struct Curl_easy *data, data->req.size = -1; /* Set the progress data */ - Curl_pgrsSetUploadCounter(data, 0); - Curl_pgrsSetDownloadCounter(data, 0); - Curl_pgrsSetUploadSize(data, -1); - Curl_pgrsSetDownloadSize(data, -1); + Curl_pgrsReset(data); /* Carry out the perform */ result = pop3_perform(data, &connected, dophase_done); @@ -1529,7 +1513,7 @@ static void pop3_easy_dtor(void *key, size_t klen, void *entry) /* Cleanup our per-request based variables */ Curl_safefree(pop3->id); Curl_safefree(pop3->custom); - free(pop3); + curlx_free(pop3); } static void pop3_conn_dtor(void *key, size_t klen, void *entry) @@ -1540,19 +1524,19 @@ static void pop3_conn_dtor(void *key, size_t klen, void *entry) DEBUGASSERT(pop3c); Curl_pp_disconnect(&pop3c->pp); Curl_safefree(pop3c->apoptimestamp); - free(pop3c); + curlx_free(pop3c); } static CURLcode pop3_setup_connection(struct Curl_easy *data, struct connectdata *conn) { struct pop3_conn *pop3c; - struct POP3 *pop3 = calloc(1, sizeof(*pop3)); + struct POP3 *pop3 = curlx_calloc(1, sizeof(*pop3)); if(!pop3 || Curl_meta_set(data, CURL_META_POP3_EASY, pop3, pop3_easy_dtor)) return CURLE_OUT_OF_MEMORY; - pop3c = calloc(1, sizeof(*pop3c)); + pop3c = curlx_calloc(1, sizeof(*pop3c)); if(!pop3c || Curl_conn_meta_set(conn, CURL_META_POP3_CONN, pop3c, pop3_conn_dtor)) return CURLE_OUT_OF_MEMORY; @@ -1744,9 +1728,8 @@ static CURLcode pop3_write(struct Curl_easy *data, const char *str, /* Did we have a partial match which has subsequently failed? */ if(prev && prev >= pop3c->eob) { - /* Strip can only be non-zero for the very first mismatch after CRLF - and then both prev and strip are equal and nothing will be output - below */ + /* Strip can only be non-zero for the first mismatch after CRLF and + then both prev and strip are equal and nothing will be output below */ while(prev && pop3c->strip) { prev--; pop3c->strip--; diff --git a/lib/progress.c b/lib/progress.c index 7b473ef3ae93..fc0164c1725a 100644 --- a/lib/progress.c +++ b/lib/progress.c @@ -25,10 +25,12 @@ #include "curl_setup.h" #include "urldata.h" -#include "sendf.h" +#include "curl_trc.h" #include "multiif.h" #include "progress.h" +#include "transfer.h" #include "curlx/timeval.h" +#include "curlx/strcopy.h" /* check rate limits within this many recent milliseconds, at minimum. */ #define MIN_RATE_LIMIT_PERIOD 3000 @@ -36,18 +38,18 @@ #ifndef CURL_DISABLE_PROGRESS_METER /* Provide a string that is 2 + 1 + 2 + 1 + 2 = 8 letters long (plus the zero byte) */ -static void time2str(char *r, curl_off_t seconds) +static void time2str(char *r, size_t rsize, curl_off_t seconds) { curl_off_t h; if(seconds <= 0) { - strcpy(r, "--:--:--"); + curlx_strcopy(r, rsize, "--:--:--", 8); return; } h = seconds / 3600; if(h <= 99) { curl_off_t m = (seconds - (h * 3600)) / 60; curl_off_t s = (seconds - (h * 3600)) - (m * 60); - curl_msnprintf(r, 9, "%2" FMT_OFF_T ":%02" FMT_OFF_T ":%02" FMT_OFF_T, + curl_msnprintf(r, rsize, "%2" FMT_OFF_T ":%02" FMT_OFF_T ":%02" FMT_OFF_T, h, m, s); } else { @@ -56,48 +58,99 @@ static void time2str(char *r, curl_off_t seconds) curl_off_t d = seconds / 86400; h = (seconds - (d * 86400)) / 3600; if(d <= 999) - curl_msnprintf(r, 9, "%3" FMT_OFF_T "d %02" FMT_OFF_T "h", d, h); + curl_msnprintf(r, rsize, "%3" FMT_OFF_T "d %02" FMT_OFF_T "h", d, h); else - curl_msnprintf(r, 9, "%7" FMT_OFF_T "d", d); + curl_msnprintf(r, rsize, "%7" FMT_OFF_T "d", d); } } /* The point of this function would be to return a string of the input data, but never longer than 6 columns (+ one zero byte). Add suffix k, M, G when suitable... */ -static char *max6data(curl_off_t bytes, char *max6) +static char *max6out(curl_off_t bytes, char *max6, size_t mlen) { - /* a signed 64-bit value is 8192 petabytes maximum */ - const char unit[] = { 'k', 'M', 'G', 'T', 'P', 0 }; - int k = 0; - if(bytes < 1000000) { - curl_msnprintf(max6, 7, "%5" CURL_FORMAT_CURL_OFF_T, bytes); - return max6; + /* a signed 64-bit value is 8192 petabytes maximum, shown as + 8.0E (exabytes)*/ + if(bytes < 100000) + curl_msnprintf(max6, mlen, "%6" CURL_FORMAT_CURL_OFF_T, bytes); + else { + const char unit[] = { 'k', 'M', 'G', 'T', 'P', 'E', 0 }; + int k = 0; + curl_off_t nbytes; + do { + nbytes = bytes / 1024; + if(nbytes < 1000) + break; + bytes = nbytes; + k++; + DEBUGASSERT(unit[k]); + } while(unit[k]); + /* xxx.yU */ + curl_msnprintf(max6, mlen, "%3" CURL_FORMAT_CURL_OFF_T + ".%" CURL_FORMAT_CURL_OFF_T "%c", nbytes, + (bytes % 1024) / (1024 / 10), unit[k]); } - - do { - curl_off_t nbytes = bytes / 1024; - if(nbytes < 1000) { - /* xxx.yU */ - curl_msnprintf(max6, 7, "%3" CURL_FORMAT_CURL_OFF_T - ".%" CURL_FORMAT_CURL_OFF_T "%c", nbytes, - (bytes%1024) / (1024/10), unit[k]); - break; - } - else if(nbytes < 100000) { - /* xxxxxU */ - curl_msnprintf(max6, 7, "%5" CURL_FORMAT_CURL_OFF_T "%c", - nbytes, unit[k]); - break; - } - bytes = nbytes; - k++; - DEBUGASSERT(unit[k]); - } while(unit[k]); return max6; } #endif +static void pgrs_speedinit(struct Curl_easy *data) +{ + memset(&data->state.keeps_speed, 0, sizeof(struct curltime)); +} + +/* + * @unittest: 1606 + */ +UNITTEST CURLcode pgrs_speedcheck(struct Curl_easy *data, + const struct curltime *pnow) +{ + if(!data->set.low_speed_time || !data->set.low_speed_limit || + Curl_xfer_recv_is_paused(data) || Curl_xfer_send_is_paused(data)) + /* A paused transfer is not qualified for speed checks */ + return CURLE_OK; + + if(data->progress.current_speed >= 0) { + if(data->progress.current_speed < data->set.low_speed_limit) { + if(!data->state.keeps_speed.tv_sec) + /* under the limit at this moment */ + data->state.keeps_speed = *pnow; + else { + /* how long has it been under the limit */ + timediff_t howlong = + curlx_ptimediff_ms(pnow, &data->state.keeps_speed); + + if(howlong >= data->set.low_speed_time * 1000) { + /* too long */ + failf(data, + "Operation too slow. " + "Less than %ld bytes/sec transferred the last %ld seconds", + data->set.low_speed_limit, + data->set.low_speed_time); + return CURLE_OPERATION_TIMEDOUT; + } + } + } + else + /* faster right now */ + data->state.keeps_speed.tv_sec = 0; + } + + /* since low speed limit is enabled, set the expire timer to make this + connection's speed get checked again in a second */ + Curl_expire(data, 1000, EXPIRE_SPEEDCHECK); + + return CURLE_OK; +} + +const struct curltime *Curl_pgrs_now(struct Curl_easy *data) +{ + struct curltime *pnow = data->multi ? + &data->multi->now : &data->progress.now; + curlx_pnow(pnow); + return pnow; +} + /* New proposed interface, 9th of February 2000: @@ -125,10 +178,19 @@ int Curl_pgrsDone(struct Curl_easy *data) * hidden */ curl_mfprintf(data->set.err, "\n"); - data->progress.speeder_c = 0; /* reset the progress meter display */ return 0; } +void Curl_pgrsReset(struct Curl_easy *data) +{ + Curl_pgrsSetUploadCounter(data, 0); + data->progress.dl.cur_size = 0; + Curl_pgrsSetUploadSize(data, -1); + Curl_pgrsSetDownloadSize(data, -1); + data->progress.speeder_c = 0; /* reset speed records */ + pgrs_speedinit(data); +} + /* reset the known transfer sizes */ void Curl_pgrsResetTransferSizes(struct Curl_easy *data) { @@ -136,6 +198,22 @@ void Curl_pgrsResetTransferSizes(struct Curl_easy *data) Curl_pgrsSetUploadSize(data, -1); } +void Curl_pgrsRecvPause(struct Curl_easy *data, bool enable) +{ + if(!enable) { + data->progress.speeder_c = 0; /* reset speed records */ + pgrs_speedinit(data); /* reset low speed measurements */ + } +} + +void Curl_pgrsSendPause(struct Curl_easy *data, bool enable) +{ + if(!enable) { + data->progress.speeder_c = 0; /* reset speed records */ + pgrs_speedinit(data); /* reset low speed measurements */ + } +} + /* * * Curl_pgrsTimeWas(). Store the timestamp time at the given label. @@ -164,7 +242,7 @@ void Curl_pgrsTimeWas(struct Curl_easy *data, timerid timer, case TIMER_POSTQUEUE: /* Queue time is accumulative from all involved redirects */ data->progress.t_postqueue += - curlx_timediff_us(timestamp, data->progress.t_startqueue); + curlx_ptimediff_us(×tamp, &data->progress.t_startqueue); break; case TIMER_STARTACCEPT: data->progress.t_acceptdata = timestamp; @@ -200,13 +278,14 @@ void Curl_pgrsTimeWas(struct Curl_easy *data, timerid timer, delta = &data->progress.t_posttransfer; break; case TIMER_REDIRECT: - data->progress.t_redirect = curlx_timediff_us(timestamp, - data->progress.start); + data->progress.t_redirect = curlx_ptimediff_us(×tamp, + &data->progress.start); data->progress.t_startqueue = timestamp; break; } if(delta) { - timediff_t us = curlx_timediff_us(timestamp, data->progress.t_startsingle); + timediff_t us = curlx_ptimediff_us(×tamp, + &data->progress.t_startsingle); if(us < 1) us = 1; /* make sure at least one microsecond passed */ *delta += us; @@ -220,116 +299,38 @@ void Curl_pgrsTimeWas(struct Curl_easy *data, timerid timer, * * @unittest: 1399 */ -struct curltime Curl_pgrsTime(struct Curl_easy *data, timerid timer) +void Curl_pgrsTime(struct Curl_easy *data, timerid timer) { - struct curltime now = curlx_now(); - - Curl_pgrsTimeWas(data, timer, now); - return now; + Curl_pgrsTimeWas(data, timer, *Curl_pgrs_now(data)); } void Curl_pgrsStartNow(struct Curl_easy *data) { struct Progress *p = &data->progress; + p->speeder_c = 0; /* reset the progress meter display */ - p->start = curlx_now(); + p->start = *Curl_pgrs_now(data); p->is_t_startransfer_set = FALSE; - p->ul.limit.start = p->start; - p->dl.limit.start = p->start; - p->ul.limit.start_size = 0; - p->dl.limit.start_size = 0; p->dl.cur_size = 0; p->ul.cur_size = 0; /* the sizes are unknown at start */ p->dl_size_known = FALSE; p->ul_size_known = FALSE; - Curl_ratelimit(data, p->start); } -/* - * This is used to handle speed limits, calculating how many milliseconds to - * wait until we are back under the speed limit, if needed. - * - * The way it works is by having a "starting point" (time & amount of data - * transferred by then) used in the speed computation, to be used instead of - * the start of the transfer. This starting point is regularly moved as - * transfer goes on, to keep getting accurate values (instead of average over - * the entire transfer). - * - * This function takes the current amount of data transferred, the amount at - * the starting point, the limit (in bytes/s), the time of the starting point - * and the current time. - * - * Returns 0 if no waiting is needed or when no waiting is needed but the - * starting point should be reset (to current); or the number of milliseconds - * to wait to get back under the speed limit. - */ -timediff_t Curl_pgrsLimitWaitTime(struct pgrs_dir *d, - curl_off_t bytes_per_sec, - struct curltime now) +void Curl_pgrs_download_inc(struct Curl_easy *data, size_t delta) { - curl_off_t bytes = d->cur_size - d->limit.start_size; - timediff_t should_ms; - timediff_t took_ms; - - /* no limit or we did not get to any bytes yet */ - if(!bytes_per_sec || !bytes) - return 0; - - /* The time it took us to have `bytes` */ - took_ms = curlx_timediff_ceil(now, d->limit.start); - - /* The time it *should* have taken us to have `bytes` - * when obeying the bytes_per_sec speed_limit. */ - if(bytes < CURL_OFF_T_MAX/1000) { - /* (1000 * bytes / (bytes / sec)) = 1000 * sec = ms */ - should_ms = (timediff_t) (1000 * bytes / bytes_per_sec); - } - else { - /* very large `bytes`, first calc the seconds it should have taken. - * if that is small enough, convert to milliseconds. */ - should_ms = (timediff_t) (bytes / bytes_per_sec); - if(should_ms < TIMEDIFF_T_MAX/1000) - should_ms *= 1000; - else - should_ms = TIMEDIFF_T_MAX; - } - - if(took_ms < should_ms) { - /* when gotten to `bytes` too fast, wait the difference */ - return should_ms - took_ms; + if(delta) { + data->progress.dl.cur_size += delta; + Curl_rlimit_drain(&data->progress.dl.rlimit, delta, Curl_pgrs_now(data)); } - return 0; -} - -/* - * Set the number of downloaded bytes so far. - */ -CURLcode Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size) -{ - data->progress.dl.cur_size = size; - return CURLE_OK; } -/* - * Update the timestamp and sizestamp to use for rate limit calculations. - */ -void Curl_ratelimit(struct Curl_easy *data, struct curltime now) +void Curl_pgrs_upload_inc(struct Curl_easy *data, size_t delta) { - /* do not set a new stamp unless the time since last update is long enough */ - if(data->set.max_recv_speed) { - if(curlx_timediff(now, data->progress.dl.limit.start) >= - MIN_RATE_LIMIT_PERIOD) { - data->progress.dl.limit.start = now; - data->progress.dl.limit.start_size = data->progress.dl.cur_size; - } - } - if(data->set.max_send_speed) { - if(curlx_timediff(now, data->progress.ul.limit.start) >= - MIN_RATE_LIMIT_PERIOD) { - data->progress.ul.limit.start = now; - data->progress.ul.limit.start_size = data->progress.ul.cur_size; - } + if(delta) { + data->progress.ul.cur_size += delta; + Curl_rlimit_drain(&data->progress.ul.rlimit, delta, Curl_pgrs_now(data)); } } @@ -367,7 +368,7 @@ void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size) void Curl_pgrsEarlyData(struct Curl_easy *data, curl_off_t sent) { - data->progress.earlydata_sent = sent; + data->progress.earlydata_sent = sent; } /* returns the average speed in bytes / second */ @@ -376,7 +377,7 @@ static curl_off_t trspeed(curl_off_t size, /* number of bytes */ { if(us < 1) return size * 1000000; - else if(size < CURL_OFF_T_MAX/1000000) + else if(size < CURL_OFF_T_MAX / 1000000) return (size * 1000000) / us; else if(us >= 1000000) return size / (us / 1000000); @@ -385,75 +386,83 @@ static curl_off_t trspeed(curl_off_t size, /* number of bytes */ } /* returns TRUE if it is time to show the progress meter */ -static bool progress_calc(struct Curl_easy *data, struct curltime now) +static bool progress_calc(struct Curl_easy *data, + const struct curltime *pnow) { - bool timetoshow = FALSE; struct Progress * const p = &data->progress; + int i_next, i_oldest, i_latest; + timediff_t duration_ms; + curl_off_t amount; /* The time spent so far (from the start) in microseconds */ - p->timespent = curlx_timediff_us(now, p->start); + p->timespent = curlx_ptimediff_us(pnow, &p->start); p->dl.speed = trspeed(p->dl.cur_size, p->timespent); p->ul.speed = trspeed(p->ul.cur_size, p->timespent); - /* Calculations done at most once a second, unless end is reached */ - if(p->lastshow != now.tv_sec) { - int countindex; /* amount of seconds stored in the speeder array */ - int nowindex = p->speeder_c% CURR_TIME; - p->lastshow = now.tv_sec; - timetoshow = TRUE; - - /* Let's do the "current speed" thing, with the dl + ul speeds - combined. Store the speed at entry 'nowindex'. */ - p->speeder[ nowindex ] = p->dl.cur_size + p->ul.cur_size; - - /* remember the exact time for this moment */ - p->speeder_time [ nowindex ] = now; - - /* advance our speeder_c counter, which is increased every time we get - here and we expect it to never wrap as 2^32 is a lot of seconds! */ + if(!p->speeder_c) { /* no previous record exists */ + p->speed_amount[0] = p->dl.cur_size + p->ul.cur_size; + p->speed_time[0] = *pnow; p->speeder_c++; - - /* figure out how many index entries of data we have stored in our speeder - array. With N_ENTRIES filled in, we have about N_ENTRIES-1 seconds of - transfer. Imagine, after one second we have filled in two entries, - after two seconds we have filled in three entries etc. */ - countindex = ((p->speeder_c >= CURR_TIME) ? CURR_TIME : p->speeder_c) - 1; - - /* first of all, we do not do this if there is no counted seconds yet */ - if(countindex) { - int checkindex; - timediff_t span_ms; - curl_off_t amount; - - /* Get the index position to compare with the 'nowindex' position. - Get the oldest entry possible. While we have less than CURR_TIME - entries, the first entry will remain the oldest. */ - checkindex = (p->speeder_c >= CURR_TIME) ? p->speeder_c%CURR_TIME : 0; - - /* Figure out the exact time for the time span */ - span_ms = curlx_timediff(now, p->speeder_time[checkindex]); - if(span_ms == 0) - span_ms = 1; /* at least one millisecond MUST have passed */ - - /* Calculate the average speed the last 'span_ms' milliseconds */ - amount = p->speeder[nowindex]- p->speeder[checkindex]; - - if(amount > (0xffffffff/1000)) - /* the 'amount' value is bigger than would fit in 32 bits if - multiplied with 1000, so we use the double math for this */ - p->current_speed = (curl_off_t) - ((double)amount/((double)span_ms/1000.0)); - else - /* the 'amount' value is small enough to fit within 32 bits even - when multiplied with 1000 */ - p->current_speed = amount * 1000/span_ms; + /* use the overall average at the start */ + p->current_speed = p->ul.speed + p->dl.speed; + p->lastshow = pnow->tv_sec; + return TRUE; + } + /* We have at least one record now. Where to put the next and + * where is the latest one? */ + i_next = p->speeder_c % CURL_SPEED_RECORDS; + i_latest = (i_next > 0) ? (i_next - 1) : (CURL_SPEED_RECORDS - 1); + + /* Make a new record only when some time has passed. + * Too frequent calls otherwise ruin the history. */ + if(curlx_ptimediff_ms(pnow, &p->speed_time[i_latest]) >= 1000) { + p->speeder_c++; + i_latest = i_next; + p->speed_amount[i_latest] = p->dl.cur_size + p->ul.cur_size; + p->speed_time[i_latest] = *pnow; + } + else if(data->req.done) { + /* When a transfer is done, and we did not have a current speed + * already, update the last record. Otherwise, stay at the speed + * we have. The last chunk of data, when rate limiting, would increase + * reported speed since it no longer measures a full second. */ + if(!p->current_speed) { + p->speed_amount[i_latest] = p->dl.cur_size + p->ul.cur_size; + p->speed_time[i_latest] = *pnow; } - else - /* the first second we use the average */ - p->current_speed = p->ul.speed + p->dl.speed; + } + else { + /* transfer ongoing, wait for more time to pass. */ + return FALSE; + } + + i_oldest = (p->speeder_c < CURL_SPEED_RECORDS) ? 0 : + ((i_latest + 1) % CURL_SPEED_RECORDS); + + /* How much we transferred between oldest and current records */ + amount = p->speed_amount[i_latest] - p->speed_amount[i_oldest]; + /* How long this took */ + duration_ms = curlx_ptimediff_ms(&p->speed_time[i_latest], + &p->speed_time[i_oldest]); + if(duration_ms <= 0) + duration_ms = 1; + + if(amount > (CURL_OFF_T_MAX / 1000)) { + /* the 'amount' value is bigger than would fit in 64 bits if + multiplied with 1000, so we use the double math for this */ + p->current_speed = + (curl_off_t)(((double)amount * 1000.0) / (double)duration_ms); + } + else { + /* the 'amount' value is small enough to fit within 32 bits even + when multiplied with 1000 */ + p->current_speed = amount * 1000 / duration_ms; + } - } /* Calculations end */ - return timetoshow; + if((p->lastshow == pnow->tv_sec) && !data->req.done) + return FALSE; + p->lastshow = pnow->tv_sec; + return TRUE; } #ifndef CURL_DISABLE_PROGRESS_METER @@ -468,7 +477,7 @@ static curl_off_t pgrs_est_percent(curl_off_t total, curl_off_t cur) if(total > 10000) return cur / (total / 100); else if(total > 0) - return (cur*100) / total; + return (cur * 100) / total; return 0; } @@ -497,7 +506,7 @@ static void progress_meter(struct Curl_easy *data) char time_left[10]; char time_total[10]; char time_spent[10]; - curl_off_t cur_secs = (curl_off_t)p->timespent/1000000; /* seconds */ + curl_off_t cur_secs = (curl_off_t)p->timespent / 1000000; /* seconds */ if(!p->headers_out) { if(data->state.resume_from) { @@ -520,16 +529,15 @@ static void progress_meter(struct Curl_easy *data) /* Since both happen at the same time, total expected duration is max. */ total_estm.secs = CURLMAX(ul_estm.secs, dl_estm.secs); /* create the three time strings */ - time2str(time_left, total_estm.secs > 0 ? (total_estm.secs - cur_secs) : 0); - time2str(time_total, total_estm.secs); - time2str(time_spent, cur_secs); + time2str(time_left, sizeof(time_left), + total_estm.secs > 0 ? (total_estm.secs - cur_secs) : 0); + time2str(time_total, sizeof(time_total), total_estm.secs); + time2str(time_spent, sizeof(time_spent), cur_secs); /* Get the total amount of data expected to get transferred */ - total_expected_size = - p->ul_size_known ? p->ul.total_size : p->ul.cur_size; + total_expected_size = p->ul_size_known ? p->ul.total_size : p->ul.cur_size; - dl_size = - p->dl_size_known ? p->dl.total_size : p->dl.cur_size; + dl_size = p->dl_size_known ? p->dl.total_size : p->dl.cur_size; /* integer overflow check */ if((CURL_OFF_T_MAX - total_expected_size) < dl_size) @@ -548,18 +556,24 @@ static void progress_meter(struct Curl_easy *data) "%3" FMT_OFF_T " %s " "%3" FMT_OFF_T " %s " "%3" FMT_OFF_T " %s %s %s %s %s %s %s", - total_estm.percent, /* 3 letters */ /* total % */ - max6data(total_expected_size, max6[2]), /* total size */ - dl_estm.percent, /* 3 letters */ /* rcvd % */ - max6data(p->dl.cur_size, max6[0]), /* rcvd size */ - ul_estm.percent, /* 3 letters */ /* xfer % */ - max6data(p->ul.cur_size, max6[1]), /* xfer size */ - max6data(p->dl.speed, max6[3]), /* avrg dl speed */ - max6data(p->ul.speed, max6[4]), /* avrg ul speed */ - time_total, /* 8 letters */ /* total time */ - time_spent, /* 8 letters */ /* time spent */ - time_left, /* 8 letters */ /* time left */ - max6data(p->current_speed, max6[5]) + total_estm.percent, /* 3 letters */ /* total % */ + max6out(total_expected_size, max6[2], + sizeof(max6[2])), /* total size */ + dl_estm.percent, /* 3 letters */ /* rcvd % */ + max6out(p->dl.cur_size, max6[0], + sizeof(max6[0])), /* rcvd size */ + ul_estm.percent, /* 3 letters */ /* xfer % */ + max6out(p->ul.cur_size, max6[1], + sizeof(max6[1])), /* xfer size */ + max6out(p->dl.speed, max6[3], + sizeof(max6[3])), /* avrg dl speed */ + max6out(p->ul.speed, max6[4], + sizeof(max6[4])), /* avrg ul speed */ + time_total, /* 8 letters */ /* total time */ + time_spent, /* 8 letters */ /* time spent */ + time_left, /* 8 letters */ /* time left */ + max6out(p->current_speed, max6[5], + sizeof(max6[5])) /* current speed */ ); /* we flush the output stream to make it appear as soon as possible */ @@ -570,12 +584,11 @@ static void progress_meter(struct Curl_easy *data) #define progress_meter(x) Curl_nop_stmt #endif - /* * Curl_pgrsUpdate() returns 0 for success or the value returned by the * progress callback! */ -static int pgrsupdate(struct Curl_easy *data, bool showprogress) +static CURLcode pgrsupdate(struct Curl_easy *data, bool showprogress) { if(!data->progress.hide) { if(data->set.fxferinfo) { @@ -589,9 +602,11 @@ static int pgrsupdate(struct Curl_easy *data, bool showprogress) data->progress.ul.cur_size); Curl_set_in_callback(data, FALSE); if(result != CURL_PROGRESSFUNC_CONTINUE) { - if(result) + if(result) { failf(data, "Callback aborted"); - return result; + return CURLE_ABORTED_BY_CALLBACK; + } + return CURLE_OK; } } else if(data->set.fprogress) { @@ -605,9 +620,11 @@ static int pgrsupdate(struct Curl_easy *data, bool showprogress) (double)data->progress.ul.cur_size); Curl_set_in_callback(data, FALSE); if(result != CURL_PROGRESSFUNC_CONTINUE) { - if(result) + if(result) { failf(data, "Callback aborted"); - return result; + return CURLE_ABORTED_BY_CALLBACK; + } + return CURLE_OK; } } @@ -615,21 +632,35 @@ static int pgrsupdate(struct Curl_easy *data, bool showprogress) progress_meter(data); } - return 0; + return CURLE_OK; } -int Curl_pgrsUpdate(struct Curl_easy *data) +static CURLcode pgrs_update(struct Curl_easy *data, + const struct curltime *pnow) { - struct curltime now = curlx_now(); /* what time is it */ - bool showprogress = progress_calc(data, now); + bool showprogress = progress_calc(data, pnow); return pgrsupdate(data, showprogress); } +CURLcode Curl_pgrsUpdate(struct Curl_easy *data) +{ + return pgrs_update(data, Curl_pgrs_now(data)); +} + +CURLcode Curl_pgrsCheck(struct Curl_easy *data) +{ + CURLcode result; + + result = pgrs_update(data, Curl_pgrs_now(data)); + if(!result && !data->req.done) + result = pgrs_speedcheck(data, Curl_pgrs_now(data)); + return result; +} + /* * Update all progress, do not do progress meter/callbacks. */ void Curl_pgrsUpdate_nometer(struct Curl_easy *data) { - struct curltime now = curlx_now(); /* what time is it */ - (void)progress_calc(data, now); + (void)progress_calc(data, Curl_pgrs_now(data)); } diff --git a/lib/progress.h b/lib/progress.h index bbe135cdbcd7..f368c2475ef9 100644 --- a/lib/progress.h +++ b/lib/progress.h @@ -26,6 +26,7 @@ #include "curlx/timeval.h" +struct Curl_easy; typedef enum { TIMER_NONE, @@ -43,24 +44,35 @@ typedef enum { TIMER_LAST /* must be last */ } timerid; +/* Get the current timestamp of the transfer */ +const struct curltime *Curl_pgrs_now(struct Curl_easy *data); + int Curl_pgrsDone(struct Curl_easy *data); void Curl_pgrsStartNow(struct Curl_easy *data); void Curl_pgrsSetDownloadSize(struct Curl_easy *data, curl_off_t size); void Curl_pgrsSetUploadSize(struct Curl_easy *data, curl_off_t size); -/* It is fine to not check the return code if 'size' is set to 0 */ -CURLcode Curl_pgrsSetDownloadCounter(struct Curl_easy *data, curl_off_t size); - +void Curl_pgrs_download_inc(struct Curl_easy *data, size_t delta); +void Curl_pgrs_upload_inc(struct Curl_easy *data, size_t delta); void Curl_pgrsSetUploadCounter(struct Curl_easy *data, curl_off_t size); -void Curl_ratelimit(struct Curl_easy *data, struct curltime now); -int Curl_pgrsUpdate(struct Curl_easy *data); + +/* perform progress update, invoking callbacks at intervals */ +CURLcode Curl_pgrsUpdate(struct Curl_easy *data); +/* perform progress update, no callbacks invoked */ void Curl_pgrsUpdate_nometer(struct Curl_easy *data); +/* perform progress update with callbacks and speed checks */ +CURLcode Curl_pgrsCheck(struct Curl_easy *data); +/* Inform progress/speedcheck about receive/send pausing */ +void Curl_pgrsRecvPause(struct Curl_easy *data, bool enable); +void Curl_pgrsSendPause(struct Curl_easy *data, bool enable); + +/* Reset sizes and couners for up- and download. */ +void Curl_pgrsReset(struct Curl_easy *data); +/* Reset sizes for up- and download. */ void Curl_pgrsResetTransferSizes(struct Curl_easy *data); -struct curltime Curl_pgrsTime(struct Curl_easy *data, timerid timer); -timediff_t Curl_pgrsLimitWaitTime(struct pgrs_dir *d, - curl_off_t speed_limit, - struct curltime now); + +void Curl_pgrsTime(struct Curl_easy *data, timerid timer); /** * Update progress timer with the elapsed time from its start to `timestamp`. * This allows updating timers later and is used by happy eyeballing, where @@ -71,4 +83,9 @@ void Curl_pgrsTimeWas(struct Curl_easy *data, timerid timer, void Curl_pgrsEarlyData(struct Curl_easy *data, curl_off_t sent); +#ifdef UNITTESTS +UNITTEST CURLcode pgrs_speedcheck(struct Curl_easy *data, + const struct curltime *pnow); +#endif + #endif /* HEADER_CURL_PROGRESS_H */ diff --git a/lib/psl.c b/lib/psl.c index 832d6d21b94a..5346a57fcec6 100644 --- a/lib/psl.c +++ b/lib/psl.c @@ -24,16 +24,11 @@ #include "curl_setup.h" -#include - #ifdef USE_LIBPSL #include "psl.h" -#include "share.h" - -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" +#include "progress.h" +#include "curl_share.h" void Curl_psl_destroy(struct PslCache *pslcache) { @@ -45,25 +40,18 @@ void Curl_psl_destroy(struct PslCache *pslcache) } } -static time_t now_seconds(void) -{ - struct curltime now = curlx_now(); - - return now.tv_sec; -} - const psl_ctx_t *Curl_psl_use(struct Curl_easy *easy) { struct PslCache *pslcache = easy->psl; const psl_ctx_t *psl; - time_t now; + time_t now_sec; if(!pslcache) return NULL; Curl_share_lock(easy, CURL_LOCK_DATA_PSL, CURL_LOCK_ACCESS_SHARED); - now = now_seconds(); - if(!pslcache->psl || pslcache->expires <= now) { + now_sec = Curl_pgrs_now(easy)->tv_sec; + if(!pslcache->psl || pslcache->expires <= now_sec) { /* Let a chance to other threads to do the job: avoids deadlock. */ Curl_share_unlock(easy, CURL_LOCK_DATA_PSL); @@ -71,8 +59,10 @@ const psl_ctx_t *Curl_psl_use(struct Curl_easy *easy) Curl_share_lock(easy, CURL_LOCK_DATA_PSL, CURL_LOCK_ACCESS_SINGLE); /* Recheck in case another thread did the job. */ - now = now_seconds(); - if(!pslcache->psl || pslcache->expires <= now) { + if(pslcache->expires <= now_sec) { + now_sec = Curl_pgrs_now(easy)->tv_sec; + } + if(!pslcache->psl || pslcache->expires <= now_sec) { bool dynamic = FALSE; time_t expires = TIME_T_MAX; @@ -80,7 +70,8 @@ const psl_ctx_t *Curl_psl_use(struct Curl_easy *easy) psl = psl_latest(NULL); dynamic = psl != NULL; /* Take care of possible time computation overflow. */ - expires = now < TIME_T_MAX - PSL_TTL ? now + PSL_TTL : TIME_T_MAX; + expires = (now_sec < TIME_T_MAX - PSL_TTL) ? + (now_sec + PSL_TTL) : TIME_T_MAX; /* Only get the built-in PSL if we do not already have the "latest". */ if(!psl && !pslcache->dynamic) @@ -95,7 +86,7 @@ const psl_ctx_t *Curl_psl_use(struct Curl_easy *easy) pslcache->expires = expires; } } - Curl_share_unlock(easy, CURL_LOCK_DATA_PSL); /* Release exclusive lock. */ + Curl_share_unlock(easy, CURL_LOCK_DATA_PSL); /* Release exclusive lock. */ Curl_share_lock(easy, CURL_LOCK_DATA_PSL, CURL_LOCK_ACCESS_SHARED); } psl = pslcache->psl; diff --git a/lib/rand.c b/lib/rand.c index cbfcbf27409b..4689a04b006a 100644 --- a/lib/rand.c +++ b/lib/rand.c @@ -24,24 +24,17 @@ #include "curl_setup.h" -#include - #ifdef HAVE_ARPA_INET_H #include #endif -#include #include "urldata.h" #include "vtls/vtls.h" -#include "sendf.h" +#include "curl_trc.h" #include "curlx/timeval.h" #include "rand.h" #include "escape.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - #ifdef _WIN32 #if defined(_WIN32_WINNT) && _WIN32_WINNT >= _WIN32_WINNT_VISTA && \ @@ -50,10 +43,6 @@ # include # ifdef _MSC_VER # pragma comment(lib, "bcrypt.lib") -# endif - /* Offered by mingw-w64 v3+. MS SDK v7.0A+. */ -# ifndef BCRYPT_USE_SYSTEM_PREFERRED_RNG -# define BCRYPT_USE_SYSTEM_PREFERRED_RNG 0x00000002 # endif # ifndef STATUS_SUCCESS # define STATUS_SUCCESS ((NTSTATUS)0x00000000L) @@ -127,7 +116,8 @@ static CURLcode weak_random(struct Curl_easy *data, static bool seeded = FALSE; unsigned int rnd; if(!seeded) { - struct curltime now = curlx_now(); + struct curltime now; + curlx_pnow(&now); randseed += (unsigned int)now.tv_usec + (unsigned int)now.tv_sec; randseed = randseed * 1103515245 + 12345; randseed = randseed * 1103515245 + 12345; @@ -235,8 +225,7 @@ CURLcode Curl_rand_bytes(struct Curl_easy *data, * size. */ -CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd, - size_t num) +CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd, size_t num) { CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT; unsigned char buffer[128]; @@ -248,7 +237,7 @@ 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; @@ -256,11 +245,11 @@ CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd, num--; /* save one for null-termination */ - result = Curl_rand(data, buffer, num/2); + result = Curl_rand(data, buffer, num / 2); if(result) return result; - Curl_hexencode(buffer, num/2, rnd, num + 1); + Curl_hexencode(buffer, num / 2, rnd, num + 1); return result; } diff --git a/lib/rand.h b/lib/rand.h index 2ba60e72976e..674cb6ee2025 100644 --- a/lib/rand.h +++ b/lib/rand.h @@ -31,9 +31,9 @@ CURLcode Curl_rand_bytes(struct Curl_easy *data, unsigned char *rnd, size_t num); #ifdef DEBUGBUILD -#define Curl_rand(a,b,c) Curl_rand_bytes((a), TRUE, (b), (c)) +#define Curl_rand(a, b, c) Curl_rand_bytes((a), TRUE, (b), (c)) #else -#define Curl_rand(a,b,c) Curl_rand_bytes((a), (b), (c)) +#define Curl_rand(a, b, c) Curl_rand_bytes((a), (b), (c)) #endif /* @@ -41,8 +41,7 @@ CURLcode Curl_rand_bytes(struct Curl_easy *data, * hexadecimal digits PLUS a null-terminating byte. It must be an odd number * size. */ -CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd, - size_t num); +CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd, size_t num); /* * Curl_rand_alnum() fills the 'rnd' buffer with a given 'num' size with random diff --git a/lib/ratelimit.c b/lib/ratelimit.c new file mode 100644 index 000000000000..feafe669c178 --- /dev/null +++ b/lib/ratelimit.c @@ -0,0 +1,199 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the 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 "curlx/timeval.h" +#include "ratelimit.h" + + +#define CURL_US_PER_SEC 1000000 +#define CURL_RLIMIT_MIN_CHUNK (16 * 1024) +#define CURL_RLIMIT_MAX_STEPS 2 /* 500ms interval */ + +void Curl_rlimit_init(struct Curl_rlimit *r, + curl_off_t rate_per_s, + curl_off_t burst_per_s, + const struct curltime *pts) +{ + curl_off_t rate_steps; + + DEBUGASSERT(rate_per_s >= 0); + DEBUGASSERT(burst_per_s >= rate_per_s || !burst_per_s); + DEBUGASSERT(pts); + r->step_us = CURL_US_PER_SEC; + r->rate_per_step = rate_per_s; + r->burst_per_step = burst_per_s; + /* On rates that are multiples of CURL_RLIMIT_MIN_CHUNK, we reduce + * the interval `step_us` from 1 second to smaller steps with at + * most CURL_RLIMIT_MAX_STEPS. + * Smaller means more CPU, but also more precision. */ + rate_steps = rate_per_s / CURL_RLIMIT_MIN_CHUNK; + rate_steps = CURLMIN(rate_steps, CURL_RLIMIT_MAX_STEPS); + if(rate_steps >= 2) { + r->step_us /= rate_steps; + r->rate_per_step /= rate_steps; + r->burst_per_step /= rate_steps; + } + r->tokens = r->rate_per_step; + r->spare_us = 0; + r->ts = *pts; + r->blocked = FALSE; +} + +void Curl_rlimit_start(struct Curl_rlimit *r, const struct curltime *pts) +{ + r->tokens = r->rate_per_step; + r->spare_us = 0; + r->ts = *pts; +} + +bool Curl_rlimit_active(struct Curl_rlimit *r) +{ + return (r->rate_per_step > 0) || r->blocked; +} + +bool Curl_rlimit_is_blocked(struct Curl_rlimit *r) +{ + return r->blocked; +} + +static void ratelimit_update(struct Curl_rlimit *r, + const struct curltime *pts) +{ + timediff_t elapsed_us, elapsed_steps; + curl_off_t token_gain; + + DEBUGASSERT(r->rate_per_step); + if((r->ts.tv_sec == pts->tv_sec) && (r->ts.tv_usec == pts->tv_usec)) + return; + + elapsed_us = curlx_ptimediff_us(pts, &r->ts); + if(elapsed_us < 0) { /* not going back in time */ + DEBUGASSERT(0); + return; + } + + elapsed_us += r->spare_us; + if(elapsed_us < r->step_us) + return; + + /* we do the update */ + r->ts = *pts; + elapsed_steps = elapsed_us / r->step_us; + r->spare_us = elapsed_us % r->step_us; + + /* How many tokens did we gain since the last update? */ + if(r->rate_per_step > (CURL_OFF_T_MAX / elapsed_steps)) + token_gain = CURL_OFF_T_MAX; + else { + token_gain = r->rate_per_step * elapsed_steps; + } + + /* Limit the token again by the burst rate per second (if set), so we + * do not suddenly have a huge number of tokens after inactivity. */ + r->tokens += token_gain; + if(r->burst_per_step && (r->tokens > r->burst_per_step)) { + r->tokens = r->burst_per_step; + } +} + +curl_off_t Curl_rlimit_avail(struct Curl_rlimit *r, + const struct curltime *pts) +{ + if(r->blocked) + return 0; + else if(r->rate_per_step) { + ratelimit_update(r, pts); + return r->tokens; + } + else + return CURL_OFF_T_MAX; +} + +void Curl_rlimit_drain(struct Curl_rlimit *r, + size_t tokens, + const struct curltime *pts) +{ + if(r->blocked || !r->rate_per_step) + return; + + ratelimit_update(r, pts); +#if SIZEOF_CURL_OFF_T <= SIZEOF_SIZE_T + if(tokens > CURL_OFF_T_MAX) { + r->tokens = CURL_OFF_T_MIN; + return; + } + else +#endif + { + curl_off_t val = (curl_off_t)tokens; + if((CURL_OFF_T_MIN + val) < r->tokens) + r->tokens -= val; + else + r->tokens = CURL_OFF_T_MIN; + } +} + +timediff_t Curl_rlimit_wait_ms(struct Curl_rlimit *r, + const struct curltime *pts) +{ + timediff_t wait_us, elapsed_us; + + if(r->blocked || !r->rate_per_step) + return 0; + ratelimit_update(r, pts); + if(r->tokens > 0) + return 0; + + /* How much time will it take tokens to become positive again? + * Deduct `spare_us` and check against already elapsed time */ + wait_us = (1 + (-r->tokens / r->rate_per_step)) * r->step_us; + wait_us -= r->spare_us; + + elapsed_us = curlx_ptimediff_us(pts, &r->ts); + if(elapsed_us >= wait_us) + return 0; + wait_us -= elapsed_us; + return (wait_us + 999) / 1000; /* in milliseconds */ +} + +void Curl_rlimit_block(struct Curl_rlimit *r, + bool activate, + const struct curltime *pts) +{ + if(!activate == !r->blocked) + return; + + r->ts = *pts; + r->blocked = activate; + if(!r->blocked) { + /* Start rate limiting fresh. The amount of time this was blocked + * does not generate extra tokens. */ + Curl_rlimit_start(r, pts); + } + else { + r->tokens = 0; + } +} diff --git a/lib/ratelimit.h b/lib/ratelimit.h new file mode 100644 index 000000000000..aa576451263c --- /dev/null +++ b/lib/ratelimit.h @@ -0,0 +1,94 @@ +#ifndef HEADER_Curl_rlimit_H +#define HEADER_Curl_rlimit_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the 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 "curlx/timeval.h" + +struct Curl_easy; + +/* This is a rate limiter that provides "tokens" to be consumed + * per second with a "burst" rate limitation. Example: + * A rate limit of 1 megabyte per second with a burst rate of 1.5MB. + * - initially 1 million tokens are available. + * - these are drained in the first second. + * - checking available tokens before the 2nd second will return 0. + * - at/after the 2nd second, 1 million tokens are available again. + * - nothing happens for a second, the 1 million tokens would grow + * to 2 million, however the burst limit caps those at 1.5 million. + * Thus: + * - setting "burst" to CURL_OFF_T_MAX would average tokens over the + * complete lifetime. E.g. for a download, at the *end* of it, the + * average rate from start to finish would be the rate limit. + * - setting "burst" to the same value as "rate" would make a + * download always try to stay *at/below* the rate and slow times will + * not generate extra tokens. + * A rate limit can be blocked, causing the available tokens to become + * always 0 until unblocked. After unblocking, the rate limiting starts + * again with no history of the past. + * Finally, a rate limiter with rate 0 will always have CURL_OFF_T_MAX + * tokens available, unless blocked. + */ + +struct Curl_rlimit { + curl_off_t rate_per_step; /* rate tokens are generated per step us */ + curl_off_t burst_per_step; /* burst rate of tokens per step us */ + timediff_t step_us; /* microseconds between token increases */ + curl_off_t tokens; /* tokens available in the next second */ + timediff_t spare_us; /* microseconds unaffecting tokens */ + struct curltime ts; /* time of the last update */ + BIT(blocked); /* blocking sets available tokens to 0 */ +}; + +void Curl_rlimit_init(struct Curl_rlimit *r, + curl_off_t rate_per_s, + curl_off_t burst_per_s, + const struct curltime *pts); + +/* Start ratelimiting with the given timestamp. Resets available tokens. */ +void Curl_rlimit_start(struct Curl_rlimit *r, const struct curltime *pts); + +/* How many milliseconds to wait until token are available again. */ +timediff_t Curl_rlimit_wait_ms(struct Curl_rlimit *r, + const struct curltime *pts); + +/* Return if rate limiting of tokens is active */ +bool Curl_rlimit_active(struct Curl_rlimit *r); +bool Curl_rlimit_is_blocked(struct Curl_rlimit *r); + +/* Return how many tokens are available to spend, may be negative */ +curl_off_t Curl_rlimit_avail(struct Curl_rlimit *r, + const struct curltime *pts); + +/* Drain tokens from the ratelimit, return how many are now available. */ +void Curl_rlimit_drain(struct Curl_rlimit *r, + size_t tokens, + const struct curltime *pts); + +/* Block/unblock ratelimiting. A blocked ratelimit has 0 tokens available. */ +void Curl_rlimit_block(struct Curl_rlimit *r, + bool activate, + const struct curltime *pts); + +#endif /* HEADER_Curl_rlimit_H */ diff --git a/lib/rename.c b/lib/rename.c deleted file mode 100644 index 4c66ce4ed0eb..000000000000 --- a/lib/rename.c +++ /dev/null @@ -1,72 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at https://curl.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the 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 "rename.h" - -#include "curl_setup.h" - -#if (!defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_COOKIES)) || \ - !defined(CURL_DISABLE_ALTSVC) - -#include "curlx/multibyte.h" -#include "curlx/timeval.h" - -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - -/* return 0 on success, 1 on error */ -int Curl_rename(const char *oldpath, const char *newpath) -{ -#if defined(_WIN32) && !defined(UNDER_CE) - /* rename() on Windows does not overwrite, so we cannot use it here. - MoveFileEx() will overwrite and is usually atomic, however it fails - when there are open handles to the file. */ - const int max_wait_ms = 1000; - struct curltime start = curlx_now(); - TCHAR *tchar_oldpath = curlx_convert_UTF8_to_tchar(oldpath); - TCHAR *tchar_newpath = curlx_convert_UTF8_to_tchar(newpath); - for(;;) { - timediff_t diff; - if(MoveFileEx(tchar_oldpath, tchar_newpath, MOVEFILE_REPLACE_EXISTING)) { - curlx_unicodefree(tchar_oldpath); - curlx_unicodefree(tchar_newpath); - break; - } - diff = curlx_timediff(curlx_now(), start); - if(diff < 0 || diff > max_wait_ms) { - curlx_unicodefree(tchar_oldpath); - curlx_unicodefree(tchar_newpath); - return 1; - } - Sleep(1); - } -#else - if(rename(oldpath, newpath)) - return 1; -#endif - return 0; -} - -#endif diff --git a/lib/request.c b/lib/request.c index 1fa568325bbf..c8781b70bf48 100644 --- a/lib/request.c +++ b/lib/request.c @@ -28,18 +28,14 @@ #include "cfilters.h" #include "curlx/dynbuf.h" #include "doh.h" -#include "multiif.h" #include "progress.h" #include "request.h" #include "sendf.h" +#include "curl_trc.h" #include "transfer.h" #include "url.h" #include "curlx/strparse.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - void Curl_req_init(struct SingleRequest *req) { memset(req, 0, sizeof(*req)); @@ -64,7 +60,7 @@ CURLcode Curl_req_soft_reset(struct SingleRequest *req, req->header = FALSE; req->headerline = 0; req->headerbytecount = 0; - req->allheadercount = 0; + req->allheadercount = 0; req->deductheadercount = 0; req->httpversion_sent = 0; req->httpversion = 0; @@ -94,7 +90,7 @@ CURLcode Curl_req_soft_reset(struct SingleRequest *req, CURLcode Curl_req_start(struct SingleRequest *req, struct Curl_easy *data) { - req->start = curlx_now(); + req->start = *Curl_pgrs_now(data); return Curl_req_soft_reset(req, data); } @@ -115,7 +111,7 @@ CURLcode Curl_req_done(struct SingleRequest *req, void Curl_req_hard_reset(struct SingleRequest *req, struct Curl_easy *data) { - struct curltime t0 = {0, 0}; + struct curltime t0 = { 0, 0 }; Curl_safefree(req->newurl); Curl_client_reset(data); @@ -132,7 +128,7 @@ void Curl_req_hard_reset(struct SingleRequest *req, struct Curl_easy *data) req->writebytecount = 0; req->start = t0; req->headerbytecount = 0; - req->allheadercount = 0; + req->allheadercount = 0; req->deductheadercount = 0; req->headerline = 0; req->offset = 0; @@ -223,7 +219,7 @@ static CURLcode xfer_send(struct Curl_easy *data, size_t body_len = *pnwritten - hds_len; Curl_debug(data, CURLINFO_DATA_OUT, buf + hds_len, body_len); data->req.writebytecount += body_len; - Curl_pgrsSetUploadCounter(data, data->req.writebytecount); + Curl_pgrs_upload_inc(data, body_len); } } } @@ -258,7 +254,7 @@ static CURLcode req_set_upload_done(struct Curl_easy *data) { DEBUGASSERT(!data->req.upload_done); data->req.upload_done = TRUE; - data->req.keepon &= ~(KEEP_SEND|KEEP_SEND_TIMED); /* we are done sending */ + data->req.keepon &= ~KEEP_SEND; /* we are done sending */ Curl_pgrsTime(data, TIMER_POSTRANSFER); Curl_creader_done(data, data->req.upload_aborted); @@ -393,6 +389,11 @@ CURLcode Curl_req_send(struct Curl_easy *data, struct dynbuf *req, return result; buf += nwritten; blen -= nwritten; + if(!blen) { + result = req_set_upload_done(data); + if(result) + return result; + } } if(blen) { @@ -420,9 +421,9 @@ bool Curl_req_want_send(struct Curl_easy *data) * - or request has buffered data to send * - or transfer connection has pending data to send */ return !data->req.done && - (((data->req.keepon & KEEP_SENDBITS) == KEEP_SEND) || - !Curl_req_sendbuf_empty(data) || - Curl_xfer_needs_flush(data)); + ((data->req.keepon & KEEP_SEND) || + !Curl_req_sendbuf_empty(data) || + Curl_xfer_needs_flush(data)); } bool Curl_req_done_sending(struct Curl_easy *data) @@ -458,8 +459,7 @@ CURLcode Curl_req_abort_sending(struct Curl_easy *data) if(!data->req.upload_done) { Curl_bufq_reset(&data->req.sendbuf); data->req.upload_aborted = TRUE; - /* no longer KEEP_SEND and KEEP_SEND_PAUSE */ - data->req.keepon &= ~KEEP_SENDBITS; + data->req.keepon &= ~KEEP_SEND; return req_set_upload_done(data); } return CURLE_OK; @@ -470,6 +470,9 @@ CURLcode Curl_req_stop_send_recv(struct Curl_easy *data) /* stop receiving and ALL sending as well, including PAUSE and HOLD. * We might still be paused on receive client writes though, so * keep those bits around. */ - data->req.keepon &= ~(KEEP_RECV|KEEP_SENDBITS); - return Curl_req_abort_sending(data); + CURLcode result = CURLE_OK; + if(data->req.keepon & KEEP_SEND) + result = Curl_req_abort_sending(data); + data->req.keepon &= ~(KEEP_RECV | KEEP_SEND); + return result; } diff --git a/lib/request.h b/lib/request.h index e12d5efdcb23..5b0d1460283b 100644 --- a/lib/request.h +++ b/lib/request.h @@ -48,7 +48,6 @@ enum upgrade101 { UPGR101_RECEIVED /* 101 response received */ }; - /* * Request specific data in the easy handle (Curl_easy). Previously, * these members were on the connectdata struct but since a conn struct may @@ -130,6 +129,7 @@ struct SingleRequest { BIT(sendbuf_init); /* sendbuf is initialized */ BIT(shutdown); /* request end will shutdown connection */ BIT(shutdown_err_ignore); /* errors in shutdown will not fail request */ + BIT(reader_started); /* client reads have started */ }; /** diff --git a/lib/rtsp.c b/lib/rtsp.c index 1f952a07cccb..063ab7eb925d 100644 --- a/lib/rtsp.c +++ b/lib/rtsp.c @@ -27,9 +27,9 @@ #ifndef CURL_DISABLE_RTSP #include "urldata.h" -#include #include "transfer.h" #include "sendf.h" +#include "curl_trc.h" #include "multiif.h" #include "http.h" #include "url.h" @@ -40,13 +40,9 @@ #include "connect.h" #include "cfilters.h" #include "strdup.h" +#include "bufref.h" #include "curlx/strparse.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - - /* meta key for storing protocol meta at easy handle */ #define CURL_META_RTSP_EASY "meta:proto:rtsp:easy" /* meta key for storing protocol meta at connection */ @@ -75,7 +71,6 @@ struct RTSP { long CSeq_recv; /* CSeq received */ }; - #define RTP_PKT_LENGTH(p) ((((unsigned int)((unsigned char)((p)[2]))) << 8) | \ ((unsigned int)((unsigned char)((p)[3])))) @@ -121,11 +116,10 @@ static CURLcode rtsp_do_pollset(struct Curl_easy *data, return Curl_pollset_add_out(data, ps, data->conn->sock[FIRSTSOCKET]); } -static -CURLcode rtp_client_write(struct Curl_easy *data, const char *ptr, size_t len); -static -CURLcode rtsp_parse_transport(struct Curl_easy *data, const char *transport); - +static CURLcode rtp_client_write(struct Curl_easy *data, const char *ptr, + size_t len); +static CURLcode rtsp_parse_transport(struct Curl_easy *data, + const char *transport); /* * RTSP handler interface. @@ -142,7 +136,7 @@ const struct Curl_handler Curl_handler_rtsp = { ZERO_NULL, /* proto_pollset */ rtsp_do_pollset, /* doing_pollset */ ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ + Curl_http_perform_pollset, /* perform_pollset */ ZERO_NULL, /* disconnect */ rtsp_rtp_write_resp, /* write_resp */ rtsp_rtp_write_resp_hd, /* write_resp_hd */ @@ -152,7 +146,7 @@ const struct Curl_handler Curl_handler_rtsp = { PORT_RTSP, /* defport */ CURLPROTO_RTSP, /* protocol */ CURLPROTO_RTSP, /* family */ - PROTOPT_NONE /* flags */ + PROTOPT_CONN_REUSE /* flags */ }; #define MAX_RTP_BUFFERSIZE 1000000 /* arbitrary */ @@ -162,7 +156,7 @@ static void rtsp_easy_dtor(void *key, size_t klen, void *entry) struct RTSP *rtsp = entry; (void)key; (void)klen; - free(rtsp); + curlx_free(rtsp); } static void rtsp_conn_dtor(void *key, size_t klen, void *entry) @@ -171,7 +165,7 @@ static void rtsp_conn_dtor(void *key, size_t klen, void *entry) (void)key; (void)klen; curlx_dyn_free(&rtspc->buf); - free(rtspc); + curlx_free(rtspc); } static CURLcode rtsp_setup_connection(struct Curl_easy *data, @@ -180,14 +174,14 @@ static CURLcode rtsp_setup_connection(struct Curl_easy *data, struct rtsp_conn *rtspc; struct RTSP *rtsp; - rtspc = calloc(1, sizeof(*rtspc)); + rtspc = curlx_calloc(1, sizeof(*rtspc)); if(!rtspc) return CURLE_OUT_OF_MEMORY; curlx_dyn_init(&rtspc->buf, MAX_RTP_BUFFERSIZE); if(Curl_conn_meta_set(conn, CURL_META_RTSP_CONN, rtspc, rtsp_conn_dtor)) return CURLE_OUT_OF_MEMORY; - rtsp = calloc(1, sizeof(struct RTSP)); + rtsp = curlx_calloc(1, sizeof(struct RTSP)); if(!rtsp || Curl_meta_set(data, CURL_META_RTSP_EASY, rtsp, rtsp_easy_dtor)) return CURLE_OUT_OF_MEMORY; @@ -195,7 +189,6 @@ static CURLcode rtsp_setup_connection(struct Curl_easy *data, return CURLE_OK; } - /* * Function to check on various aspects of a connection. */ @@ -215,18 +208,14 @@ static unsigned int rtsp_conncheck(struct Curl_easy *data, return ret_val; } - static CURLcode rtsp_connect(struct Curl_easy *data, bool *done) { struct rtsp_conn *rtspc = Curl_conn_meta_get(data->conn, CURL_META_RTSP_CONN); - CURLcode httpStatus; if(!rtspc) return CURLE_FAILED_INIT; - httpStatus = Curl_http_connect(data, done); - /* Initialize the CSeq if not already done */ if(data->state.rtsp_next_client_CSeq == 0) data->state.rtsp_next_client_CSeq = 1; @@ -234,8 +223,8 @@ static CURLcode rtsp_connect(struct Curl_easy *data, bool *done) data->state.rtsp_next_server_CSeq = 1; rtspc->rtp_channel = -1; - - return httpStatus; + *done = TRUE; + return CURLE_OK; } static CURLcode rtsp_done(struct Curl_easy *data, @@ -278,7 +267,6 @@ static CURLcode rtsp_done(struct Curl_easy *data, return httpStatus; } - static CURLcode rtsp_setup_body(struct Curl_easy *data, Curl_RtspReq rtspreq, struct dynbuf *reqp) @@ -298,7 +286,8 @@ static CURLcode rtsp_setup_body(struct Curl_easy *data, } else { if(data->set.postfields) { - size_t plen = strlen(data->set.postfields); + size_t plen = (data->set.postfieldsize >= 0) ? + (size_t)data->set.postfieldsize : strlen(data->set.postfields); req_clen = (curl_off_t)plen; result = Curl_creader_set_buf(data, data->set.postfields, plen); } @@ -327,9 +316,8 @@ static CURLcode rtsp_setup_body(struct Curl_easy *data, if(rtspreq == RTSPREQ_SET_PARAMETER || rtspreq == RTSPREQ_GET_PARAMETER) { if(!Curl_checkheaders(data, STRCONST("Content-Type"))) { - result = curlx_dyn_addn(reqp, - STRCONST("Content-Type: " - "text/parameters\r\n")); + result = curlx_dyn_addn(reqp, STRCONST("Content-Type: " + "text/parameters\r\n")); if(result) return result; } @@ -337,9 +325,8 @@ static CURLcode rtsp_setup_body(struct Curl_easy *data, if(rtspreq == RTSPREQ_ANNOUNCE) { if(!Curl_checkheaders(data, STRCONST("Content-Type"))) { - result = curlx_dyn_addn(reqp, - STRCONST("Content-Type: " - "application/sdp\r\n")); + result = curlx_dyn_addn(reqp, STRCONST("Content-Type: " + "application/sdp\r\n")); if(result) return result; } @@ -391,7 +378,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done) to this origin */ if(!data->state.first_host) { - data->state.first_host = strdup(conn->host.name); + data->state.first_host = curlx_strdup(conn->host.name); if(!data->state.first_host) return CURLE_OUT_OF_MEMORY; @@ -480,7 +467,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done) if(rtspreq == RTSPREQ_SETUP && !p_transport) { /* New Transport: setting? */ if(data->set.str[STRING_RTSP_TRANSPORT]) { - free(data->state.aptr.rtsp_transport); + curlx_free(data->state.aptr.rtsp_transport); data->state.aptr.rtsp_transport = curl_maprintf("Transport: %s\r\n", data->set.str[STRING_RTSP_TRANSPORT]); @@ -506,7 +493,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done) /* Accept-Encoding header */ if(!Curl_checkheaders(data, STRCONST("Accept-Encoding")) && data->set.str[STRING_ENCODING]) { - free(data->state.aptr.accept_encoding); + curlx_free(data->state.aptr.accept_encoding); data->state.aptr.accept_encoding = curl_maprintf("Accept-Encoding: %s\r\n", data->set.str[STRING_ENCODING]); @@ -545,9 +532,10 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done) /* Referrer */ Curl_safefree(data->state.aptr.ref); - if(data->state.referer && !Curl_checkheaders(data, STRCONST("Referer"))) - data->state.aptr.ref = curl_maprintf("Referer: %s\r\n", - data->state.referer); + if(Curl_bufref_ptr(&data->state.referer) && + !Curl_checkheaders(data, STRCONST("Referer"))) + data->state.aptr.ref = + curl_maprintf("Referer: %s\r\n", Curl_bufref_ptr(&data->state.referer)); p_referrer = data->state.aptr.ref; @@ -562,7 +550,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done) /* Check to see if there is a range set in the custom headers */ if(!Curl_checkheaders(data, STRCONST("Range")) && data->state.range) { - free(data->state.aptr.rangeline); + curlx_free(data->state.aptr.rangeline); data->state.aptr.rangeline = curl_maprintf("Range: %s\r\n", data->state.range); p_range = data->state.aptr.rangeline; @@ -667,8 +655,7 @@ static CURLcode rtsp_do(struct Curl_easy *data, bool *done) /* if a request-body has been sent off, we make sure this progress is noted properly */ Curl_pgrsSetUploadCounter(data, data->req.writebytecount); - if(Curl_pgrsUpdate(data)) - result = CURLE_ABORTED_BY_CALLBACK; + result = Curl_pgrsUpdate(data); } out: curlx_dyn_free(&req_buffer); @@ -935,7 +922,7 @@ static CURLcode rtsp_rtp_write_resp(struct Curl_easy *data, blen, rtspc->in_header, data->req.done, rtspc->state, data->req.size)); if(!result && (is_eos || blen)) { - result = Curl_client_write(data, CLIENTWRITE_BODY| + result = Curl_client_write(data, CLIENTWRITE_BODY | (is_eos ? CLIENTWRITE_EOS : 0), buf, blen); } @@ -958,8 +945,8 @@ static CURLcode rtsp_rtp_write_resp_hd(struct Curl_easy *data, return rtsp_rtp_write_resp(data, buf, blen, is_eos); } -static -CURLcode rtp_client_write(struct Curl_easy *data, const char *ptr, size_t len) +static CURLcode rtp_client_write(struct Curl_easy *data, const char *ptr, + size_t len) { size_t wrote; curl_write_callback writeit; @@ -1070,8 +1057,8 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, const char *header) return CURLE_OK; } -static -CURLcode rtsp_parse_transport(struct Curl_easy *data, const char *transport) +static CURLcode rtsp_parse_transport(struct Curl_easy *data, + const char *transport) { /* If we receive multiple Transport response-headers, the linterleaved channels of each response header is recorded and used together for @@ -1113,5 +1100,4 @@ CURLcode rtsp_parse_transport(struct Curl_easy *data, const char *transport) return CURLE_OK; } - #endif /* CURL_DISABLE_RTSP */ diff --git a/lib/rtsp.h b/lib/rtsp.h index 59f20a9f1672..7b42efde2860 100644 --- a/lib/rtsp.h +++ b/lib/rtsp.h @@ -32,7 +32,7 @@ CURLcode Curl_rtsp_parseheader(struct Curl_easy *data, const char *header); #else /* disabled */ -#define Curl_rtsp_parseheader(x,y) CURLE_NOT_BUILT_IN +#define Curl_rtsp_parseheader(x, y) CURLE_NOT_BUILT_IN #endif /* CURL_DISABLE_RTSP */ diff --git a/lib/select.c b/lib/select.c index 7818082e7543..5761084242d1 100644 --- a/lib/select.c +++ b/lib/select.c @@ -28,27 +28,18 @@ #error "We cannot compile without select() or poll() support." #endif -#include - #ifdef HAVE_SYS_SELECT_H #include #elif defined(HAVE_UNISTD_H) #include #endif -#include - #include "urldata.h" #include "connect.h" #include "select.h" #include "curl_trc.h" #include "curlx/timediff.h" #include "curlx/wait.h" -#include "curlx/warnless.h" - -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" #ifndef HAVE_POLL /* @@ -150,19 +141,19 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ num = 0; if(readfd0 != CURL_SOCKET_BAD) { pfd[num].fd = readfd0; - pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI; + pfd[num].events = POLLRDNORM | POLLIN | POLLRDBAND | POLLPRI; pfd[num].revents = 0; num++; } if(readfd1 != CURL_SOCKET_BAD) { pfd[num].fd = readfd1; - pfd[num].events = POLLRDNORM|POLLIN|POLLRDBAND|POLLPRI; + pfd[num].events = POLLRDNORM | POLLIN | POLLRDBAND | POLLPRI; pfd[num].revents = 0; num++; } if(writefd != CURL_SOCKET_BAD) { pfd[num].fd = writefd; - pfd[num].events = POLLWRNORM|POLLOUT|POLLPRI; + pfd[num].events = POLLWRNORM | POLLOUT | POLLPRI; pfd[num].revents = 0; num++; } @@ -174,23 +165,23 @@ int Curl_socket_check(curl_socket_t readfd0, /* two sockets to read from */ r = 0; num = 0; if(readfd0 != CURL_SOCKET_BAD) { - if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP)) + if(pfd[num].revents & (POLLRDNORM | POLLIN | POLLERR | POLLHUP)) r |= CURL_CSELECT_IN; - if(pfd[num].revents & (POLLPRI|POLLNVAL)) + if(pfd[num].revents & (POLLPRI | POLLNVAL)) r |= CURL_CSELECT_ERR; num++; } if(readfd1 != CURL_SOCKET_BAD) { - if(pfd[num].revents & (POLLRDNORM|POLLIN|POLLERR|POLLHUP)) + if(pfd[num].revents & (POLLRDNORM | POLLIN | POLLERR | POLLHUP)) r |= CURL_CSELECT_IN2; - if(pfd[num].revents & (POLLPRI|POLLNVAL)) + if(pfd[num].revents & (POLLPRI | POLLNVAL)) r |= CURL_CSELECT_ERR; num++; } if(writefd != CURL_SOCKET_BAD) { - if(pfd[num].revents & (POLLWRNORM|POLLOUT)) + if(pfd[num].revents & (POLLWRNORM | POLLOUT)) r |= CURL_CSELECT_OUT; - if(pfd[num].revents & (POLLERR|POLLHUP|POLLPRI|POLLNVAL)) + if(pfd[num].revents & (POLLERR | POLLHUP | POLLPRI | POLLNVAL)) r |= CURL_CSELECT_ERR; } @@ -269,7 +260,7 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms) if(ufds[i].revents & POLLHUP) ufds[i].revents |= POLLIN; if(ufds[i].revents & POLLERR) - ufds[i].revents |= POLLIN|POLLOUT; + ufds[i].revents |= POLLIN | POLLOUT; } #else /* HAVE_POLL */ @@ -284,15 +275,15 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms) if(ufds[i].fd == CURL_SOCKET_BAD) continue; VERIFY_SOCK(ufds[i].fd); - if(ufds[i].events & (POLLIN|POLLOUT|POLLPRI| - POLLRDNORM|POLLWRNORM|POLLRDBAND)) { + if(ufds[i].events & (POLLIN |POLLOUT |POLLPRI | + POLLRDNORM | POLLWRNORM | POLLRDBAND)) { if(ufds[i].fd > maxfd) maxfd = ufds[i].fd; - if(ufds[i].events & (POLLRDNORM|POLLIN)) + if(ufds[i].events & (POLLRDNORM | POLLIN)) FD_SET(ufds[i].fd, &fds_read); - if(ufds[i].events & (POLLWRNORM|POLLOUT)) + if(ufds[i].events & (POLLWRNORM | POLLOUT)) FD_SET(ufds[i].fd, &fds_write); - if(ufds[i].events & (POLLRDBAND|POLLPRI)) + if(ufds[i].events & (POLLRDBAND | POLLPRI)) FD_SET(ufds[i].fd, &fds_err); } } @@ -364,7 +355,7 @@ void Curl_pollfds_cleanup(struct curl_pollfds *cpfds) { DEBUGASSERT(cpfds); if(cpfds->allocated_pfds) { - free(cpfds->pfds); + curlx_free(cpfds->pfds); } memset(cpfds, 0, sizeof(*cpfds)); } @@ -374,13 +365,13 @@ static CURLcode cpfds_increase(struct curl_pollfds *cpfds, unsigned int inc) struct pollfd *new_fds; unsigned int new_count = cpfds->count + inc; - new_fds = calloc(new_count, sizeof(struct pollfd)); + new_fds = curlx_calloc(new_count, sizeof(struct pollfd)); if(!new_fds) return CURLE_OUT_OF_MEMORY; memcpy(new_fds, cpfds->pfds, cpfds->count * sizeof(struct pollfd)); if(cpfds->allocated_pfds) - free(cpfds->pfds); + curlx_free(cpfds->pfds); cpfds->pfds = new_fds; cpfds->count = new_count; cpfds->allocated_pfds = TRUE; @@ -521,7 +512,7 @@ void Curl_pollset_init(struct easy_pollset *ps) struct easy_pollset *Curl_pollset_create(void) { - struct easy_pollset *ps = calloc(1, sizeof(*ps)); + struct easy_pollset *ps = curlx_calloc(1, sizeof(*ps)); if(ps) Curl_pollset_init(ps); return ps; @@ -533,11 +524,11 @@ void Curl_pollset_cleanup(struct easy_pollset *ps) DEBUGASSERT(ps->init == CURL_EASY_POLLSET_MAGIC); #endif if(ps->sockets != ps->def_sockets) { - free(ps->sockets); + curlx_free(ps->sockets); ps->sockets = ps->def_sockets; } if(ps->actions != ps->def_actions) { - free(ps->actions); + curlx_free(ps->actions); ps->actions = ps->def_actions; } ps->count = CURL_ARRAYSIZE(ps->def_sockets); @@ -583,9 +574,9 @@ CURLcode Curl_pollset_change(struct Curl_easy *data, if(!VALID_SOCK(sock)) return CURLE_BAD_FUNCTION_ARGUMENT; - 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 */ + 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->n; ++i) { if(ps->sockets[i] == sock) { ps->actions[i] &= (unsigned char)(~remove_flags); @@ -614,21 +605,21 @@ CURLcode Curl_pollset_change(struct Curl_easy *data, ps->count, new_count); if(new_count <= ps->count) return CURLE_OUT_OF_MEMORY; - nsockets = calloc(new_count, sizeof(nsockets[0])); + nsockets = curlx_calloc(new_count, sizeof(nsockets[0])); if(!nsockets) return CURLE_OUT_OF_MEMORY; - nactions = calloc(new_count, sizeof(nactions[0])); + nactions = curlx_calloc(new_count, sizeof(nactions[0])); if(!nactions) { - free(nsockets); + curlx_free(nsockets); return CURLE_OUT_OF_MEMORY; } memcpy(nsockets, ps->sockets, ps->count * sizeof(ps->sockets[0])); memcpy(nactions, ps->actions, ps->count * sizeof(ps->actions[0])); if(ps->sockets != ps->def_sockets) - free(ps->sockets); + curlx_free(ps->sockets); ps->sockets = nsockets; if(ps->actions != ps->def_actions) - free(ps->actions); + curlx_free(ps->actions); ps->actions = nactions; ps->count = new_count; } @@ -668,7 +659,7 @@ int Curl_pollset_poll(struct Curl_easy *data, if(!ps->n) return curlx_wait_ms(timeout_ms); - pfds = calloc(ps->n, sizeof(*pfds)); + pfds = curlx_calloc(ps->n, sizeof(*pfds)); if(!pfds) return -1; @@ -689,7 +680,7 @@ int Curl_pollset_poll(struct Curl_easy *data, } result = Curl_poll(pfds, npfds, timeout_ms); - free(pfds); + curlx_free(pfds); return result; } @@ -711,7 +702,7 @@ void Curl_pollset_check(struct Curl_easy *data, *pwant_read = *pwant_write = FALSE; } -bool Curl_pollset_want_read(struct Curl_easy *data, +bool Curl_pollset_want_recv(struct Curl_easy *data, struct easy_pollset *ps, curl_socket_t sock) { @@ -723,3 +714,16 @@ bool Curl_pollset_want_read(struct Curl_easy *data, } return FALSE; } + +bool Curl_pollset_want_send(struct Curl_easy *data, + struct easy_pollset *ps, + curl_socket_t sock) +{ + unsigned int i; + (void)data; + for(i = 0; i < ps->n; ++i) { + if((ps->sockets[i] == sock) && (ps->actions[i] & CURL_POLL_OUT)) + return TRUE; + } + return FALSE; +} diff --git a/lib/select.h b/lib/select.h index a23921ceb999..c5f1c59be02f 100644 --- a/lib/select.h +++ b/lib/select.h @@ -47,11 +47,10 @@ #define POLLHUP 0x10 #define POLLNVAL 0x20 -struct pollfd -{ - curl_socket_t fd; - short events; - short revents; +struct pollfd { + curl_socket_t fd; + short events; + short revents; }; #endif @@ -76,9 +75,9 @@ struct pollfd int Curl_socket_check(curl_socket_t readfd, curl_socket_t readfd2, curl_socket_t writefd, timediff_t timeout_ms); -#define SOCKET_READABLE(x,z) \ +#define SOCKET_READABLE(x, z) \ Curl_socket_check(x, CURL_SOCKET_BAD, CURL_SOCKET_BAD, z) -#define SOCKET_WRITABLE(x,z) \ +#define SOCKET_WRITABLE(x, z) \ Curl_socket_check(CURL_SOCKET_BAD, CURL_SOCKET_BAD, x, z) int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms); @@ -90,32 +89,33 @@ int Curl_poll(struct pollfd ufds[], unsigned int nfds, timediff_t timeout_ms); #ifdef USE_WINSOCK #define VALID_SOCK(s) ((s) < INVALID_SOCKET) #define FDSET_SOCK(x) 1 -#define VERIFY_SOCK(x) do { \ - if(!VALID_SOCK(x)) { \ - SET_SOCKERRNO(SOCKEINVAL); \ - return -1; \ - } \ -} while(0) +#define VERIFY_SOCK(x) \ + do { \ + if(!VALID_SOCK(x)) { \ + SET_SOCKERRNO(SOCKEINVAL); \ + return -1; \ + } \ + } while(0) #else #define VALID_SOCK(s) ((s) >= 0) /* If the socket is small enough to get set or read from an fdset */ #define FDSET_SOCK(s) ((s) < FD_SETSIZE) -#define VERIFY_SOCK(x) do { \ - if(!VALID_SOCK(x) || !FDSET_SOCK(x)) { \ - SET_SOCKERRNO(SOCKEINVAL); \ - return -1; \ - } \ +#define VERIFY_SOCK(x) \ + do { \ + if(!VALID_SOCK(x) || !FDSET_SOCK(x)) { \ + SET_SOCKERRNO(SOCKEINVAL); \ + return -1; \ + } \ } while(0) #endif - /* Keep the sockets to poll for an easy handle. * `actions` are bitmaps of CURL_POLL_IN and CURL_POLL_OUT. * Starts with small capacity, grows on demand. */ -#define EZ_POLLSET_DEF_COUNT 2 +#define EZ_POLLSET_DEF_COUNT 2 struct easy_pollset { curl_socket_t *sockets; @@ -133,7 +133,6 @@ struct easy_pollset { #define CURL_EASY_POLLSET_MAGIC 0x7a657370 #endif - /* allocate and initialise */ struct easy_pollset *Curl_pollset_create(void); @@ -154,25 +153,30 @@ void Curl_pollset_move(struct easy_pollset *to, struct easy_pollset *from); */ CURLcode Curl_pollset_change(struct Curl_easy *data, struct easy_pollset *ps, curl_socket_t sock, - int add_flags, int remove_flags); + int add_flags, + int remove_flags) WARN_UNUSED_RESULT; CURLcode Curl_pollset_set(struct Curl_easy *data, struct easy_pollset *ps, curl_socket_t sock, - bool do_in, bool do_out); + bool do_in, bool do_out) WARN_UNUSED_RESULT; #define Curl_pollset_add_in(data, ps, sock) \ - Curl_pollset_change((data), (ps), (sock), CURL_POLL_IN, 0) + Curl_pollset_change((data), (ps), (sock), CURL_POLL_IN, 0) +#define Curl_pollset_remove_in(data, ps, sock) \ + Curl_pollset_change((data), (ps), (sock), 0, CURL_POLL_IN) #define Curl_pollset_add_out(data, ps, sock) \ - Curl_pollset_change((data), (ps), (sock), CURL_POLL_OUT, 0) + Curl_pollset_change((data), (ps), (sock), CURL_POLL_OUT, 0) +#define Curl_pollset_remove_out(data, ps, sock) \ + Curl_pollset_change((data), (ps), (sock), 0, CURL_POLL_OUT) #define Curl_pollset_add_inout(data, ps, sock) \ - Curl_pollset_change((data), (ps), (sock), \ - CURL_POLL_IN|CURL_POLL_OUT, 0) + 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) + 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) + Curl_pollset_change((data), (ps), (sock), \ + CURL_POLL_OUT, CURL_POLL_IN) /* return < = on error, 0 on timeout or how many sockets are ready */ int Curl_pollset_poll(struct Curl_easy *data, @@ -187,10 +191,12 @@ void Curl_pollset_check(struct Curl_easy *data, struct easy_pollset *ps, curl_socket_t sock, bool *pwant_read, bool *pwant_write); -/** - * Return TRUE if the pollset contains socket with CURL_POLL_IN. - */ -bool Curl_pollset_want_read(struct Curl_easy *data, +/* TRUE if the pollset contains socket with CURL_POLL_IN. */ +bool Curl_pollset_want_recv(struct Curl_easy *data, + struct easy_pollset *ps, + curl_socket_t sock); +/* TRUE if the pollset contains socket with CURL_POLL_OUT. */ +bool Curl_pollset_want_send(struct Curl_easy *data, struct easy_pollset *ps, curl_socket_t sock); diff --git a/lib/sendf.c b/lib/sendf.c index c6d84127620b..b50e3dcac1b0 100644 --- a/lib/sendf.c +++ b/lib/sendf.c @@ -34,31 +34,18 @@ #include #endif -#include - #include "urldata.h" #include "sendf.h" +#include "curl_trc.h" #include "transfer.h" #include "cfilters.h" #include "connect.h" -#include "content_encoding.h" #include "cw-out.h" #include "cw-pause.h" -#include "vtls/vtls.h" -#include "vssh/ssh.h" -#include "easyif.h" #include "multiif.h" #include "strerror.h" -#include "select.h" -#include "strdup.h" #include "http2.h" #include "progress.h" -#include "curlx/warnless.h" -#include "ws.h" - -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" static CURLcode do_init_writer_stack(struct Curl_easy *data); @@ -74,13 +61,14 @@ CURLcode Curl_client_write(struct Curl_easy *data, CURLcode result; /* it is one of those, at least */ - DEBUGASSERT(type & (CLIENTWRITE_BODY|CLIENTWRITE_HEADER|CLIENTWRITE_INFO)); + DEBUGASSERT(type & + (CLIENTWRITE_BODY | CLIENTWRITE_HEADER | CLIENTWRITE_INFO)); /* BODY is only BODY (with optional EOS) */ DEBUGASSERT(!(type & CLIENTWRITE_BODY) || - ((type & ~(CLIENTWRITE_BODY|CLIENTWRITE_EOS)) == 0)); + ((type & ~(CLIENTWRITE_BODY | CLIENTWRITE_EOS)) == 0)); /* INFO is only INFO (with optional EOS) */ DEBUGASSERT(!(type & CLIENTWRITE_INFO) || - ((type & ~(CLIENTWRITE_INFO|CLIENTWRITE_EOS)) == 0)); + ((type & ~(CLIENTWRITE_INFO | CLIENTWRITE_EOS)) == 0)); if(!data->req.writer_stack) { result = do_init_writer_stack(data); @@ -101,7 +89,7 @@ static void cl_reset_writer(struct Curl_easy *data) while(writer) { data->req.writer_stack = writer->next; writer->cwt->do_close(data, writer); - free(writer); + curlx_free(writer); writer = data->req.writer_stack; } } @@ -109,10 +97,11 @@ static void cl_reset_writer(struct Curl_easy *data) static void cl_reset_reader(struct Curl_easy *data) { struct Curl_creader *reader = data->req.reader_stack; + data->req.reader_started = FALSE; while(reader) { data->req.reader_stack = reader->next; reader->crt->do_close(data, reader); - free(reader); + curlx_free(reader); reader = data->req.reader_stack; } } @@ -210,20 +199,7 @@ 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_MAX) { - return SIZE_MAX; - } -#endif - else { - return (size_t)remain_diff; - } + return curlx_sotouz_range(limit - data->req.bytecount, 0, SIZE_MAX); } return SIZE_MAX; } @@ -243,8 +219,10 @@ static CURLcode cw_download_write(struct Curl_easy *data, size_t nwrite, excess_len = 0; bool is_connect = !!(type & CLIENTWRITE_CONNECT); - if(!is_connect && !ctx->started_response) { + if(!ctx->started_response && + !(type & (CLIENTWRITE_INFO | CLIENTWRITE_CONNECT))) { Curl_pgrsTime(data, TIMER_STARTTRANSFER); + Curl_rlimit_start(&data->progress.dl.rlimit, Curl_pgrs_now(data)); ctx->started_response = TRUE; } @@ -315,11 +293,12 @@ static CURLcode cw_download_write(struct Curl_easy *data, if(result) return result; } + /* Update stats, write and report progress */ - data->req.bytecount += nwrite; - result = Curl_pgrsSetDownloadCounter(data, data->req.bytecount); - if(result) - return result; + if(nwrite) { + data->req.bytecount += nwrite; + Curl_pgrs_download_inc(data, nwrite); + } if(excess_len) { if(!data->req.ignorebody) { @@ -385,7 +364,7 @@ CURLcode Curl_cwriter_create(struct Curl_cwriter **pwriter, void *p; DEBUGASSERT(cwt->cwriter_size >= sizeof(struct Curl_cwriter)); - p = calloc(1, cwt->cwriter_size); + p = curlx_calloc(1, cwt->cwriter_size); if(!p) goto out; @@ -398,7 +377,7 @@ CURLcode Curl_cwriter_create(struct Curl_cwriter **pwriter, out: *pwriter = result ? NULL : writer; if(result) - free(writer); + curlx_free(writer); return result; } @@ -407,7 +386,7 @@ void Curl_cwriter_free(struct Curl_easy *data, { if(writer) { writer->cwt->do_close(data, writer); - free(writer); + curlx_free(writer); } } @@ -681,11 +660,7 @@ static CURLcode cr_in_read(struct Curl_easy *data, } /* respect length limitations */ if(ctx->total_len >= 0) { - curl_off_t remain = ctx->total_len - ctx->read_len; - if(remain <= 0) - blen = 0; - else if(remain < (curl_off_t)blen) - blen = (size_t)remain; + blen = curlx_sotouz_range(ctx->total_len - ctx->read_len, 0, blen); } nread = 0; if(ctx->read_cb && blen) { @@ -803,7 +778,7 @@ static CURLcode cr_in_resume_from(struct Curl_easy *data, } /* when seekerr == CURL_SEEKFUNC_CANTSEEK (cannot seek to offset) */ do { - char scratch[4*1024]; + char scratch[4 * 1024]; size_t readthisamountnow = (offset - passed > (curl_off_t)sizeof(scratch)) ? sizeof(scratch) : @@ -953,7 +928,7 @@ CURLcode Curl_creader_create(struct Curl_creader **preader, void *p; DEBUGASSERT(crt->creader_size >= sizeof(struct Curl_creader)); - p = calloc(1, crt->creader_size); + p = curlx_calloc(1, crt->creader_size); if(!p) goto out; @@ -966,7 +941,7 @@ CURLcode Curl_creader_create(struct Curl_creader **preader, out: *preader = result ? NULL : reader; if(result) - free(reader); + curlx_free(reader); return result; } @@ -974,7 +949,7 @@ void Curl_creader_free(struct Curl_easy *data, struct Curl_creader *reader) { if(reader) { reader->crt->do_close(data, reader); - free(reader); + curlx_free(reader); } } @@ -1108,8 +1083,7 @@ static CURLcode cr_lc_add(struct Curl_easy *data) struct Curl_creader *reader = NULL; CURLcode result; - result = Curl_creader_create(&reader, data, &cr_lc, - CURL_CR_CONTENT_ENCODE); + result = Curl_creader_create(&reader, data, &cr_lc, CURL_CR_CONTENT_ENCODE); if(!result) result = Curl_creader_add(data, reader); @@ -1211,6 +1185,7 @@ CURLcode Curl_client_read(struct Curl_easy *data, char *buf, size_t blen, DEBUGASSERT(blen); DEBUGASSERT(nread); DEBUGASSERT(eos); + *nread = 0; if(!data->req.reader_stack) { result = Curl_creader_set_fread(data, data->state.infilesize); @@ -1218,9 +1193,26 @@ CURLcode Curl_client_read(struct Curl_easy *data, char *buf, size_t blen, return result; DEBUGASSERT(data->req.reader_stack); } + if(!data->req.reader_started) { + Curl_rlimit_start(&data->progress.ul.rlimit, Curl_pgrs_now(data)); + data->req.reader_started = TRUE; + } + if(Curl_rlimit_active(&data->progress.ul.rlimit)) { + curl_off_t ul_avail = Curl_rlimit_avail(&data->progress.ul.rlimit, + Curl_pgrs_now(data)); + if(ul_avail <= 0) { + result = CURLE_OK; + *eos = FALSE; + goto out; + } + if(ul_avail < (curl_off_t)blen) + blen = (size_t)ul_avail; + } result = Curl_creader_read(data, data->req.reader_stack, buf, blen, nread, eos); + +out: CURL_TRC_READ(data, "client_read(len=%zu) -> %d, nread=%zu, eos=%d", blen, result, *nread, *eos); return result; @@ -1366,9 +1358,9 @@ static CURLcode cr_buf_resume_from(struct Curl_easy *data, /* already started reading? */ if(ctx->index) return CURLE_READ_ERROR; - if(offset <= 0) + boffset = curlx_sotouz_range(offset, 0, SIZE_MAX); + if(!boffset) return CURLE_OK; - boffset = (size_t)offset; if(boffset > ctx->blen) return CURLE_READ_ERROR; @@ -1442,6 +1434,7 @@ CURLcode Curl_creader_unpause(struct Curl_easy *data) while(reader) { result = reader->crt->cntrl(data, reader, CURL_CRCNTRL_UNPAUSE); + CURL_TRC_READ(data, "unpausing %s -> %d", reader->crt->name, result); if(result) break; reader = reader->next; @@ -1479,5 +1472,4 @@ struct Curl_creader *Curl_creader_get_by_type(struct Curl_easy *data, return r; } return NULL; - } diff --git a/lib/sendf.h b/lib/sendf.h index 686744390102..a11010d8ad6a 100644 --- a/lib/sendf.h +++ b/lib/sendf.h @@ -26,8 +26,6 @@ #include "curl_setup.h" -#include "curl_trc.h" - /** * Type of data that is being written to the client (application) * - data written can be either BODY or META data @@ -42,15 +40,20 @@ * BODY, INFO and HEADER should not be mixed, as this would lead to * confusion on how to interpret/format/convert the data. */ -#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 */ -#define CLIENTWRITE_EOS (1<<7) /* End Of transfer download Stream */ -#define CLIENTWRITE_0LEN (1<<8) /* write even 0-length buffers */ +#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 */ +#define CLIENTWRITE_EOS (1 << 7) /* End Of transfer download Stream */ +#define CLIENTWRITE_0LEN (1 << 8) /* write even 0-length buffers */ + +/* Forward declarations */ +struct Curl_creader; +struct Curl_cwriter; +struct Curl_easy; /** * Write `len` bytes at `prt` to the client. `type` indicates what @@ -202,7 +205,6 @@ CURLcode Curl_cwriter_def_write(struct Curl_easy *data, void Curl_cwriter_def_close(struct Curl_easy *data, struct Curl_cwriter *writer); - typedef enum { CURL_CRCNTRL_REWIND, CURL_CRCNTRL_UNPAUSE, @@ -403,7 +405,6 @@ void Curl_creader_done(struct Curl_easy *data, int premature); struct Curl_creader *Curl_creader_get_by_type(struct Curl_easy *data, const struct Curl_crtype *crt); - /** * Set the client reader to provide 0 bytes, immediate EOS. */ diff --git a/lib/setopt.c b/lib/setopt.c index 7097c7f7b015..e3b5146b770d 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -24,8 +24,6 @@ #include "curl_setup.h" -#include - #ifdef HAVE_NETINET_IN_H #include #endif @@ -41,30 +39,25 @@ #include "progress.h" #include "content_encoding.h" #include "strcase.h" -#include "share.h" +#include "curl_share.h" #include "vtls/vtls.h" -#include "curlx/warnless.h" -#include "sendf.h" +#include "curl_trc.h" #include "hostip.h" #include "http2.h" #include "setopt.h" -#include "multiif.h" #include "altsvc.h" #include "hsts.h" #include "tftp.h" #include "strdup.h" #include "escape.h" - -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" +#include "bufref.h" static CURLcode setopt_set_timeout_sec(timediff_t *ptimeout_ms, long secs) { if(secs < 0) return CURLE_BAD_FUNCTION_ARGUMENT; -#if LONG_MAX > (TIMEDIFF_T_MAX/1000) - if(secs > (TIMEDIFF_T_MAX/1000)) { +#if LONG_MAX > (TIMEDIFF_T_MAX / 1000) + if(secs > (TIMEDIFF_T_MAX / 1000)) { *ptimeout_ms = TIMEDIFF_T_MAX; return CURLE_OK; } @@ -98,7 +91,7 @@ CURLcode Curl_setstropt(char **charp, const char *s) if(strlen(s) > CURL_MAX_INPUT_LENGTH) return CURLE_BAD_FUNCTION_ARGUMENT; - *charp = strdup(s); + *charp = curlx_strdup(s); if(!*charp) return CURLE_OUT_OF_MEMORY; } @@ -119,8 +112,8 @@ CURLcode Curl_setblobopt(struct curl_blob **blobp, if(blob->len > CURL_MAX_INPUT_LENGTH) return CURLE_BAD_FUNCTION_ARGUMENT; nblob = (struct curl_blob *) - malloc(sizeof(struct curl_blob) + - ((blob->flags & CURL_BLOB_COPY) ? blob->len : 0)); + curlx_malloc(sizeof(struct curl_blob) + + ((blob->flags & CURL_BLOB_COPY) ? blob->len : 0)); if(!nblob) return CURLE_OUT_OF_MEMORY; *nblob = *blob; @@ -158,10 +151,10 @@ static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp) return result; } - free(*userp); + curlx_free(*userp); *userp = user; - free(*passwdp); + curlx_free(*passwdp); *passwdp = passwd; return CURLE_OK; @@ -185,19 +178,19 @@ static CURLcode setstropt_interface(char *option, char **devp, if(result) return result; } - free(*devp); + curlx_free(*devp); *devp = dev; - free(*ifacep); + curlx_free(*ifacep); *ifacep = iface; - free(*hostp); + curlx_free(*hostp); *hostp = host; return CURLE_OK; } -#define C_SSLVERSION_VALUE(x) (x & 0xffff) +#define C_SSLVERSION_VALUE(x) (x & 0xffff) #define C_SSLVERSION_MAX_VALUE(x) ((unsigned long)x & 0xffff0000) static CURLcode protocol2num(const char *str, curl_prot_t *val) @@ -212,7 +205,7 @@ static CURLcode protocol2num(const char *str, curl_prot_t *val) return CURLE_BAD_FUNCTION_ARGUMENT; if(curl_strequal(str, "all")) { - *val = ~(curl_prot_t) 0; + *val = ~(curl_prot_t)0; return CURLE_OK; } @@ -221,7 +214,7 @@ static CURLcode protocol2num(const char *str, curl_prot_t *val) size_t tlen; str = strchr(str, ','); - tlen = str ? (size_t) (str - token) : strlen(token); + tlen = str ? (size_t)(str - token) : strlen(token); if(tlen) { const struct Curl_handler *h = Curl_getn_scheme_handler(token, tlen); @@ -260,7 +253,7 @@ static CURLcode httpauth(struct Curl_easy *data, bool proxy, /* switch off bits we cannot support */ #ifndef USE_NTLM - auth &= ~CURLAUTH_NTLM; /* no NTLM support */ + auth &= ~CURLAUTH_NTLM; /* no NTLM support */ #endif #ifndef USE_SPNEGO auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without GSS-API @@ -528,7 +521,7 @@ static CURLcode setopt_bool(struct Curl_easy *data, CURLoption option, case CURLOPT_HTTP09_ALLOWED: s->http09_allowed = enabled; break; -#if !defined(CURL_DISABLE_COOKIES) +#ifndef CURL_DISABLE_COOKIES case CURLOPT_COOKIESESSION: /* * Set this option to TRUE to start a new "cookie session". It will @@ -791,8 +784,7 @@ static CURLcode setopt_bool(struct Curl_easy *data, CURLoption option, case CURLOPT_SSL_SESSIONID_CACHE: s->ssl.primary.cache_session = enabled; #ifndef CURL_DISABLE_PROXY - s->proxy_ssl.primary.cache_session = - s->ssl.primary.cache_session; + s->proxy_ssl.primary.cache_session = s->ssl.primary.cache_session; #endif break; #ifdef USE_SSH @@ -814,7 +806,7 @@ static CURLcode setopt_bool(struct Curl_easy *data, CURLoption option, s->tcp_keepalive = enabled; break; case CURLOPT_TCP_FASTOPEN: -#if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN) || \ +#if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN) || \ defined(TCP_FASTOPEN_CONNECT) s->tcp_fastopen = enabled; break; @@ -870,7 +862,12 @@ static CURLcode value_range(long *value, long below_error, long min, long max) static CURLcode setopt_long(struct Curl_easy *data, CURLoption option, long arg) { +#if !defined(CURL_DISABLE_PROXY) || \ + !defined(CURL_DISABLE_HTTP) || \ + defined(HAVE_GSSAPI) || \ + defined(USE_IPV6) unsigned long uarg = (unsigned long)arg; +#endif bool set = FALSE; CURLcode result = setopt_bool(data, option, arg, &set); struct UserDefined *s = &data->set; @@ -996,9 +993,9 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option, #endif #ifndef CURL_DISABLE_PROXY case CURLOPT_PROXYPORT: - if((arg < 0) || (arg > 65535)) + if((arg < 0) || (arg > UINT16_MAX)) return CURLE_BAD_FUNCTION_ARGUMENT; - s->proxyport = (unsigned short)arg; + s->proxyport = (uint16_t)arg; break; case CURLOPT_PROXYAUTH: @@ -1097,8 +1094,8 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option, #ifdef HAVE_GSSAPI case CURLOPT_GSSAPI_DELEGATION: - s->gssapi_delegation = (unsigned char)uarg& - (CURLGSSAPI_DELEGATION_POLICY_FLAG|CURLGSSAPI_DELEGATION_FLAG); + s->gssapi_delegation = (unsigned char)uarg & + (CURLGSSAPI_DELEGATION_POLICY_FLAG | CURLGSSAPI_DELEGATION_FLAG); break; #endif @@ -1144,7 +1141,7 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option, case CURLOPT_IPRESOLVE: if((arg < CURL_IPRESOLVE_WHATEVER) || (arg > CURL_IPRESOLVE_V6)) return CURLE_BAD_FUNCTION_ARGUMENT; - s->ipver = (unsigned char) arg; + s->ipver = (unsigned char)arg; break; case CURLOPT_CONNECT_ONLY: @@ -1154,7 +1151,6 @@ static CURLcode setopt_long(struct Curl_easy *data, CURLoption option, s->connect_only_ws = (arg == 2); break; - #ifdef USE_SSH case CURLOPT_SSH_AUTH_TYPES: s->ssh_auth_types = (int)arg; @@ -1413,8 +1409,8 @@ static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option, break; #endif /* ! CURL_DISABLE_FORM_API */ #endif /* ! CURL_DISABLE_HTTP */ -#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \ - !defined(CURL_DISABLE_IMAP) +#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \ + !defined(CURL_DISABLE_IMAP) # ifndef CURL_DISABLE_MIME case CURLOPT_MIMEPOST: /* @@ -1444,8 +1440,7 @@ static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option, if(!s->err) s->err = stderr; break; - case CURLOPT_SHARE: - { + case CURLOPT_SHARE: { struct Curl_share *set = va_arg(param, struct Curl_share *); /* disconnect from old share, if any */ @@ -1492,7 +1487,7 @@ static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option, /* enable cookies since we now use a share that uses cookies! */ data->cookies = data->share->cookies; } -#endif /* CURL_DISABLE_HTTP */ +#endif /* CURL_DISABLE_HTTP */ #ifndef CURL_DISABLE_HSTS if(data->share->hsts) { /* first free the private one if any */ @@ -1509,8 +1504,8 @@ static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option, } /* check for host cache not needed, * it will be done by curl_easy_perform */ + break; } - break; #ifdef USE_HTTP2 case CURLOPT_STREAM_DEPENDS: @@ -1530,9 +1525,9 @@ static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option, } #ifndef CURL_DISABLE_COOKIES -static CURLcode cookielist(struct Curl_easy *data, - const char *ptr) +static CURLcode cookielist(struct Curl_easy *data, const char *ptr) { + CURLcode result = CURLE_OK; if(!ptr) return CURLE_OK; @@ -1554,14 +1549,15 @@ static CURLcode cookielist(struct Curl_easy *data, } else if(curl_strequal(ptr, "RELOAD")) { /* reload cookies from file */ - Curl_cookie_loadfiles(data); + return Curl_cookie_loadfiles(data); } else { if(!data->cookies) { /* if cookie engine was not running, activate it */ - data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE); + data->cookies = Curl_cookie_init(); if(!data->cookies) return CURLE_OUT_OF_MEMORY; + data->state.cookie_engine = TRUE; } /* general protection against mistakes and abuse */ @@ -1571,19 +1567,18 @@ static CURLcode cookielist(struct Curl_easy *data, Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); if(checkprefix("Set-Cookie:", ptr)) /* HTTP Header format line */ - Curl_cookie_add(data, data->cookies, TRUE, FALSE, ptr + 11, NULL, - NULL, TRUE); + result = Curl_cookie_add(data, data->cookies, TRUE, FALSE, ptr + 11, + NULL, NULL, TRUE); else /* Netscape format line */ - Curl_cookie_add(data, data->cookies, FALSE, FALSE, ptr, NULL, - NULL, TRUE); + result = Curl_cookie_add(data, data->cookies, FALSE, FALSE, ptr, NULL, + NULL, TRUE); Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); } - return CURLE_OK; + return result; } -static CURLcode cookiefile(struct Curl_easy *data, - const char *ptr) +static CURLcode cookiefile(struct Curl_easy *data, const char *ptr) { /* * Set cookie file to read and parse. Can be used multiple times. @@ -1637,8 +1632,7 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option, case CURLOPT_PROXY_SSL_CIPHER_LIST: if(Curl_ssl_supports(data, SSLSUPP_CIPHER_LIST)) { /* set a list of cipher we want to use in the SSL connection for proxy */ - return Curl_setstropt(&s->str[STRING_SSL_CIPHER_LIST_PROXY], - ptr); + return Curl_setstropt(&s->str[STRING_SSL_CIPHER_LIST_PROXY], ptr); } else return CURLE_NOT_BUILT_IN; @@ -1654,8 +1648,7 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option, case CURLOPT_PROXY_TLS13_CIPHERS: if(Curl_ssl_supports(data, SSLSUPP_TLS13_CIPHERSUITES)) /* set preferred list of TLS 1.3 cipher suites for proxy */ - return Curl_setstropt(&s->str[STRING_SSL_CIPHER13_LIST_PROXY], - ptr); + return Curl_setstropt(&s->str[STRING_SSL_CIPHER13_LIST_PROXY], ptr); else return CURLE_NOT_BUILT_IN; #endif @@ -1678,31 +1671,29 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option, /* * A string with POST data. Makes curl HTTP POST. Even if it is NULL. * If needed, CURLOPT_POSTFIELDSIZE must have been set prior to - * CURLOPT_COPYPOSTFIELDS and not altered later. + * CURLOPT_COPYPOSTFIELDS and not altered later. */ if(!ptr || s->postfieldsize == -1) result = Curl_setstropt(&s->str[STRING_COPYPOSTFIELDS], ptr); else { + size_t pflen; + if(s->postfieldsize < 0) return CURLE_BAD_FUNCTION_ARGUMENT; -#if SIZEOF_CURL_OFF_T > SIZEOF_SIZE_T - /* - * Check that requested length does not overflow the size_t type. - */ - else if(s->postfieldsize > SIZE_MAX) + pflen = curlx_sotouz_range(s->postfieldsize, 0, SIZE_MAX); + if(pflen == SIZE_MAX) return CURLE_OUT_OF_MEMORY; -#endif else { /* 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. */ - char *p = Curl_memdup0(ptr, (size_t)s->postfieldsize); + char *p = Curl_memdup0(ptr, pflen); if(!p) return CURLE_OUT_OF_MEMORY; else { - free(s->str[STRING_COPYPOSTFIELDS]); + curlx_free(s->str[STRING_COPYPOSTFIELDS]); s->str[STRING_COPYPOSTFIELDS] = p; } } @@ -1735,9 +1726,12 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option, * */ if(ptr && !*ptr) { - char all[256]; - Curl_all_content_encodings(all, sizeof(all)); - return Curl_setstropt(&s->str[STRING_ENCODING], all); + ptr = Curl_get_content_encodings(); + if(ptr) + s->str[STRING_ENCODING] = ptr; + else + result = CURLE_OUT_OF_MEMORY; + return result; } return Curl_setstropt(&s->str[STRING_ENCODING], ptr); @@ -1759,12 +1753,8 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option, /* * String to set in the HTTP Referer: field. */ - if(data->state.referer_alloc) { - Curl_safefree(data->state.referer); - data->state.referer_alloc = FALSE; - } result = Curl_setstropt(&s->str[STRING_SET_REFERER], ptr); - data->state.referer = s->str[STRING_SET_REFERER]; + Curl_bufref_set(&data->state.referer, s->str[STRING_SET_REFERER], 0, NULL); break; case CURLOPT_USERAGENT: @@ -1793,11 +1783,12 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option, * Activate the cookie parser. This may or may not already * have been made. */ - struct CookieInfo *newcookies = - Curl_cookie_init(data, NULL, data->cookies, s->cookiesession); - if(!newcookies) + if(!data->cookies) + data->cookies = Curl_cookie_init(); + if(!data->cookies) result = CURLE_OUT_OF_MEMORY; - data->cookies = newcookies; + else + data->state.cookie_engine = TRUE; } break; @@ -1840,7 +1831,7 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option, * to use the socks proxy. */ return Curl_setstropt(&s->str[STRING_PRE_PROXY], ptr); -#endif /* CURL_DISABLE_PROXY */ +#endif /* CURL_DISABLE_PROXY */ #ifndef CURL_DISABLE_PROXY case CURLOPT_SOCKS5_GSSAPI_SERVICE: @@ -1976,12 +1967,8 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option, /* * The URL to fetch. */ - if(data->state.url_alloc) { - Curl_safefree(data->state.url); - data->state.url_alloc = FALSE; - } result = Curl_setstropt(&s->str[STRING_SET_URL], ptr); - data->state.url = s->str[STRING_SET_URL]; + Curl_bufref_set(&data->state.url, s->str[STRING_SET_URL], 0, NULL); break; case CURLOPT_USERPWD: @@ -2035,10 +2022,10 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option, result = Curl_urldecode(p, 0, &s->str[STRING_PROXYPASSWORD], NULL, REJECT_ZERO); } - free(u); - free(p); - } + curlx_free(u); + curlx_free(p); break; + } case CURLOPT_PROXYUSERNAME: /* * authentication username to use in the operation @@ -2068,12 +2055,7 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option, /* * pass CURLU to set URL */ - if(data->state.url_alloc) { - Curl_safefree(data->state.url); - data->state.url_alloc = FALSE; - } - else - data->state.url = NULL; + Curl_bufref_free(&data->state.url); Curl_safefree(s->str[STRING_SET_URL]); s->uh = (CURLU *)ptr; break; @@ -2165,8 +2147,9 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option, * Set the client IP to send through HAProxy PROXY protocol */ result = Curl_setstropt(&s->str[STRING_HAPROXY_CLIENT_IP], ptr); - /* enable the HAProxy protocol */ - s->haproxyprotocol = TRUE; + + /* enable the HAProxy protocol if an IP is provided */ + s->haproxyprotocol = !!s->str[STRING_HAPROXY_CLIENT_IP]; break; #endif @@ -2199,8 +2182,7 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option, */ #ifdef USE_SSL if(Curl_ssl_supports(data, SSLSUPP_PINNEDPUBKEY)) - return Curl_setstropt(&s->str[STRING_SSL_PINNEDPUBLICKEY_PROXY], - ptr); + return Curl_setstropt(&s->str[STRING_SSL_PINNEDPUBLICKEY_PROXY], ptr); #endif return CURLE_NOT_BUILT_IN; #endif @@ -2302,8 +2284,7 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option, * Specify colon-delimited list of signature scheme names. */ if(Curl_ssl_supports(data, SSLSUPP_SIGNATURE_ALGORITHMS)) - return Curl_setstropt(&s->str[STRING_SSL_SIGNATURE_ALGORITHMS], - ptr); + return Curl_setstropt(&s->str[STRING_SSL_SIGNATURE_ALGORITHMS], ptr); return CURLE_NOT_BUILT_IN; #endif #ifdef USE_SSH @@ -2345,8 +2326,7 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option, * Option to allow for the SHA256 of the host public key to be checked * for validation purposes. */ - return Curl_setstropt(&s->str[STRING_SSH_HOST_PUBLIC_KEY_SHA256], - ptr); + return Curl_setstropt(&s->str[STRING_SSH_HOST_PUBLIC_KEY_SHA256], ptr); case CURLOPT_SSH_HOSTKEYDATA: /* @@ -2357,17 +2337,27 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option, #endif /* USE_LIBSSH2 */ #endif /* USE_SSH */ case CURLOPT_PROTOCOLS_STR: - if(ptr) - return protocol2num(ptr, &s->allowed_protocols); - /* make a NULL argument reset to default */ - s->allowed_protocols = (curl_prot_t) CURLPROTO_ALL; + if(ptr) { + curl_prot_t protos; + result = protocol2num(ptr, &protos); + if(!result) + s->allowed_protocols = protos; + } + else + /* make a NULL argument reset to default */ + s->allowed_protocols = (curl_prot_t)CURLPROTO_ALL; break; case CURLOPT_REDIR_PROTOCOLS_STR: - if(ptr) - return protocol2num(ptr, &s->redir_protocols); - /* make a NULL argument reset to default */ - s->redir_protocols = (curl_prot_t) CURLPROTO_REDIR; + if(ptr) { + curl_prot_t protos; + result = protocol2num(ptr, &protos); + if(!result) + s->redir_protocols = protos; + } + else + /* make a NULL argument reset to default */ + s->redir_protocols = (curl_prot_t)CURLPROTO_REDIR; break; case CURLOPT_DEFAULT_PROTOCOL: @@ -2541,7 +2531,7 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option, if(result) return result; if(ptr) - (void)Curl_altsvc_load(data->asi, ptr); + return Curl_altsvc_load(data->asi, ptr); break; #endif /* ! CURL_DISABLE_ALTSVC */ #ifdef USE_ECH @@ -2559,17 +2549,13 @@ static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option, } /* set tls_ech flag value, preserving CLA_CFG bit */ if(!strcmp(ptr, "false")) - s->tls_ech = CURLECH_DISABLE | - (s->tls_ech & CURLECH_CLA_CFG); + s->tls_ech = (s->tls_ech & CURLECH_CLA_CFG) | CURLECH_DISABLE; else if(!strcmp(ptr, "grease")) - s->tls_ech = CURLECH_GREASE | - (s->tls_ech & CURLECH_CLA_CFG); + s->tls_ech = (s->tls_ech & CURLECH_CLA_CFG) | CURLECH_GREASE; else if(!strcmp(ptr, "true")) - s->tls_ech = CURLECH_ENABLE | - (s->tls_ech & CURLECH_CLA_CFG); + s->tls_ech = (s->tls_ech & CURLECH_CLA_CFG) | CURLECH_ENABLE; else if(!strcmp(ptr, "hard")) - s->tls_ech = CURLECH_HARD | - (s->tls_ech & CURLECH_CLA_CFG); + s->tls_ech = (s->tls_ech & CURLECH_CLA_CFG) | CURLECH_HARD; else if(plen > 5 && !strncmp(ptr, "ecl:", 4)) { result = Curl_setstropt(&s->str[STRING_ECH_CONFIG], ptr + 4); if(result) @@ -2826,6 +2812,8 @@ static CURLcode setopt_offt(struct Curl_easy *data, CURLoption option, if(offt < 0) return CURLE_BAD_FUNCTION_ARGUMENT; s->max_send_speed = offt; + Curl_rlimit_init(&data->progress.ul.rlimit, offt, offt, + Curl_pgrs_now(data)); break; case CURLOPT_MAX_RECV_SPEED_LARGE: /* @@ -2835,6 +2823,8 @@ static CURLcode setopt_offt(struct Curl_easy *data, CURLoption option, if(offt < 0) return CURLE_BAD_FUNCTION_ARGUMENT; s->max_recv_speed = offt; + Curl_rlimit_init(&data->progress.dl.rlimit, offt, offt, + Curl_pgrs_now(data)); break; case CURLOPT_RESUME_FROM_LARGE: /* @@ -2894,8 +2884,7 @@ static CURLcode setopt_blob(struct Curl_easy *data, CURLoption option, /* * Blob that holds Issuer certificate to check certificates issuer */ - return Curl_setblobopt(&s->blobs[BLOB_SSL_ISSUERCERT_PROXY], - blob); + return Curl_setblobopt(&s->blobs[BLOB_SSL_ISSUERCERT_PROXY], blob); #endif case CURLOPT_SSLKEY_BLOB: /* diff --git a/lib/setopt.h b/lib/setopt.h index c323dd74a379..0dd60c785f93 100644 --- a/lib/setopt.h +++ b/lib/setopt.h @@ -28,7 +28,7 @@ CURLcode Curl_setopt_SSLVERSION(struct Curl_easy *data, CURLoption option, long arg); #else -#define Curl_setopt_SSLVERSION(a,b,c) CURLE_NOT_BUILT_IN +#define Curl_setopt_SSLVERSION(a, b, c) CURLE_NOT_BUILT_IN #endif CURLcode Curl_setstropt(char **charp, const char *s) WARN_UNUSED_RESULT; diff --git a/lib/setup-os400.h b/lib/setup-os400.h index ef7baca67eff..4cb0d89c3882 100644 --- a/lib/setup-os400.h +++ b/lib/setup-os400.h @@ -24,7 +24,6 @@ * ***************************************************************************/ - /* OS/400 netdb.h does not define NI_MAXHOST. */ #define NI_MAXHOST 1025 @@ -37,15 +36,13 @@ typedef unsigned long u_int32_t; /* OS/400 has no idea of a tty! */ #define isatty(fd) 0 - /* Workaround bug in IBM QADRT runtime library: * function puts() does not output the implicit trailing newline. */ #include /* Be sure it is loaded. */ #undef puts -#define puts(s) (fputs((s), stdout) == EOF? EOF: putchar('\n')) - +#define puts(s) (fputs((s), stdout) == EOF ? EOF : putchar('\n')) /* System API wrapper prototypes & definitions to support ASCII parameters. */ @@ -79,7 +76,6 @@ extern OM_uint32 Curl_gss_import_name_a(OM_uint32 * minor_status, gss_name_t * out_name); #define gss_import_name Curl_gss_import_name_a - extern OM_uint32 Curl_gss_display_status_a(OM_uint32 * minor_status, OM_uint32 status_value, int status_type, gss_OID mech_type, @@ -87,7 +83,6 @@ extern OM_uint32 Curl_gss_display_status_a(OM_uint32 * minor_status, gss_buffer_t status_string); #define gss_display_status Curl_gss_display_status_a - extern OM_uint32 Curl_gss_init_sec_context_a(OM_uint32 * minor_status, gss_cred_id_t cred_handle, gss_ctx_id_t * context_handle, @@ -104,13 +99,11 @@ extern OM_uint32 Curl_gss_init_sec_context_a(OM_uint32 * minor_status, OM_uint32 * time_rec); #define gss_init_sec_context Curl_gss_init_sec_context_a - -extern OM_uint32 Curl_gss_delete_sec_context_a(OM_uint32 * minor_status, - gss_ctx_id_t * context_handle, +extern OM_uint32 Curl_gss_delete_sec_context_a(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, gss_buffer_t output_token); #define gss_delete_sec_context Curl_gss_delete_sec_context_a - /* LDAP wrappers. */ #define BerValue struct berval diff --git a/lib/setup-vms.h b/lib/setup-vms.h index 0fd5e542b775..17bf5a07a26d 100644 --- a/lib/setup-vms.h +++ b/lib/setup-vms.h @@ -38,9 +38,9 @@ /* Hide the stuff we are overriding */ #define getenv decc_getenv #ifdef __DECC -# if __INITIAL_POINTER_SIZE != 64 -# define getpwuid decc_getpwuid -# endif +# if __INITIAL_POINTER_SIZE != 64 +# define getpwuid decc_getpwuid +# endif #endif #include char *decc$getenv(const char *__name); @@ -51,34 +51,34 @@ char *decc$getenv(const char *__name); #undef getenv #undef getpwuid -#define getenv vms_getenv +#define getenv vms_getenv #define getpwuid vms_getpwuid /* VAX needs these in upper case when compiling exact case */ #define sys$assign SYS$ASSIGN #define sys$dassgn SYS$DASSGN -#define sys$qiow SYS$QIOW +#define sys$qiow SYS$QIOW #ifdef __DECC -# if __INITIAL_POINTER_SIZE -# pragma __pointer_size __save -# endif +# if __INITIAL_POINTER_SIZE +# pragma __pointer_size __save +# endif #endif #if __USE_LONG_GID_T -# define decc_getpwuid DECC$__LONG_GID_GETPWUID +# define decc_getpwuid DECC$__LONG_GID_GETPWUID #else -# if __INITIAL_POINTER_SIZE -# define decc_getpwuid decc$__32_getpwuid -# else -# define decc_getpwuid decc$getpwuid -# endif +# if __INITIAL_POINTER_SIZE +# define decc_getpwuid decc$__32_getpwuid +# else +# define decc_getpwuid decc$getpwuid +# endif #endif - struct passwd *decc_getpwuid(uid_t uid); +struct passwd *decc_getpwuid(uid_t uid); #ifdef __DECC -# if __INITIAL_POINTER_SIZE == 32 +# if __INITIAL_POINTER_SIZE == 32 /* Translate the path, but only if the path is a VMS file specification */ /* The translation is usually only needed for older versions of VMS */ static char *vms_translate_path(const char *path) @@ -100,18 +100,18 @@ static char *vms_translate_path(const char *path) return (char *)path; } } -# else - /* VMS translate path is actually not needed on the current 64-bit */ - /* VMS platforms, so instead of figuring out the pointer settings */ - /* Change it to a noop */ -# define vms_translate_path(__path) __path -# endif +# else + /* VMS translate path is actually not needed on the current 64-bit */ + /* VMS platforms, so instead of figuring out the pointer settings */ + /* Change it to a noop */ +# define vms_translate_path(__path) __path +# endif #endif #ifdef __DECC -# if __INITIAL_POINTER_SIZE -# pragma __pointer_size __restore -# endif +# if __INITIAL_POINTER_SIZE +# pragma __pointer_size __restore +# endif #endif static char *vms_getenv(const char *envvar) @@ -137,7 +137,6 @@ static char *vms_getenv(const char *envvar) return result; } - static struct passwd vms_passwd_cache; static struct passwd *vms_getpwuid(uid_t uid) @@ -146,11 +145,11 @@ static struct passwd *vms_getpwuid(uid_t uid) /* Hack needed to support 64-bit builds, decc_getpwnam is 32-bit only */ #ifdef __DECC -# if __INITIAL_POINTER_SIZE +# if __INITIAL_POINTER_SIZE __char_ptr32 unix_path; -# else +# else char *unix_path; -# endif +# endif #else char *unix_path; #endif @@ -191,182 +190,181 @@ static struct passwd *vms_getpwuid(uid_t uid) /* Bug - VMS OpenSSL and Kerberos universal symbols are in uppercase only */ /* VMS libraries should have universal symbols in exact and uppercase */ -#define ASN1_INTEGER_get ASN1_INTEGER_GET -#define ASN1_STRING_data ASN1_STRING_DATA -#define ASN1_STRING_length ASN1_STRING_LENGTH -#define ASN1_STRING_print ASN1_STRING_PRINT -#define ASN1_STRING_to_UTF8 ASN1_STRING_TO_UTF8 -#define ASN1_STRING_type ASN1_STRING_TYPE -#define BIO_ctrl BIO_CTRL -#define BIO_free BIO_FREE -#define BIO_new BIO_NEW -#define BIO_s_mem BIO_S_MEM -#define BN_bn2bin BN_BN2BIN -#define BN_num_bits BN_NUM_BITS +#define ASN1_INTEGER_get ASN1_INTEGER_GET +#define ASN1_STRING_data ASN1_STRING_DATA +#define ASN1_STRING_length ASN1_STRING_LENGTH +#define ASN1_STRING_print ASN1_STRING_PRINT +#define ASN1_STRING_to_UTF8 ASN1_STRING_TO_UTF8 +#define ASN1_STRING_type ASN1_STRING_TYPE +#define BIO_ctrl BIO_CTRL +#define BIO_free BIO_FREE +#define BIO_new BIO_NEW +#define BIO_s_mem BIO_S_MEM +#define BN_bn2bin BN_BN2BIN +#define BN_num_bits BN_NUM_BITS #define CRYPTO_cleanup_all_ex_data CRYPTO_CLEANUP_ALL_EX_DATA -#define CRYPTO_free CRYPTO_FREE -#define CRYPTO_malloc CRYPTO_MALLOC -#define CONF_modules_load_file CONF_MODULES_LOAD_FILE +#define CRYPTO_free CRYPTO_FREE +#define CRYPTO_malloc CRYPTO_MALLOC +#define CONF_modules_load_file CONF_MODULES_LOAD_FILE #ifdef __VAX # ifdef VMS_OLD_SSL /* Ancient OpenSSL on VAX/VMS missing this constant */ # define CONF_MFLAGS_IGNORE_MISSING_FILE 0x10 # undef CONF_modules_load_file - static int CONF_modules_load_file(const char *filename, - const char *appname, - unsigned long flags) { - return 1; - } +static int CONF_modules_load_file(const char *filename, + const char *appname, + unsigned long flags) { + return 1; +} # endif #endif -#define DES_ecb_encrypt DES_ECB_ENCRYPT -#define DES_set_key DES_SET_KEY -#define DES_set_odd_parity DES_SET_ODD_PARITY -#define ENGINE_ctrl ENGINE_CTRL -#define ENGINE_ctrl_cmd ENGINE_CTRL_CMD -#define ENGINE_finish ENGINE_FINISH -#define ENGINE_free ENGINE_FREE -#define ENGINE_get_first ENGINE_GET_FIRST -#define ENGINE_get_id ENGINE_GET_ID -#define ENGINE_get_next ENGINE_GET_NEXT -#define ENGINE_init ENGINE_INIT +#define DES_ecb_encrypt DES_ECB_ENCRYPT +#define DES_set_key DES_SET_KEY +#define DES_set_odd_parity DES_SET_ODD_PARITY +#define ENGINE_ctrl ENGINE_CTRL +#define ENGINE_ctrl_cmd ENGINE_CTRL_CMD +#define ENGINE_finish ENGINE_FINISH +#define ENGINE_free ENGINE_FREE +#define ENGINE_get_first ENGINE_GET_FIRST +#define ENGINE_get_id ENGINE_GET_ID +#define ENGINE_get_next ENGINE_GET_NEXT +#define ENGINE_init ENGINE_INIT #define ENGINE_load_builtin_engines ENGINE_LOAD_BUILTIN_ENGINES -#define ENGINE_load_private_key ENGINE_LOAD_PRIVATE_KEY -#define ENGINE_set_default ENGINE_SET_DEFAULT -#define ERR_clear_error ERR_CLEAR_ERROR -#define ERR_error_string ERR_ERROR_STRING -#define ERR_error_string_n ERR_ERROR_STRING_N -#define ERR_free_strings ERR_FREE_STRINGS -#define ERR_get_error ERR_GET_ERROR -#define ERR_peek_error ERR_PEEK_ERROR -#define ERR_remove_state ERR_REMOVE_STATE -#define EVP_PKEY_copy_parameters EVP_PKEY_COPY_PARAMETERS -#define EVP_PKEY_free EVP_PKEY_FREE -#define EVP_cleanup EVP_CLEANUP -#define GENERAL_NAMES_free GENERAL_NAMES_FREE -#define i2d_X509_PUBKEY I2D_X509_PUBKEY -#define MD4_Final MD4_FINAL -#define MD4_Init MD4_INIT -#define MD4_Update MD4_UPDATE -#define MD5_Final MD5_FINAL -#define MD5_Init MD5_INIT -#define MD5_Update MD5_UPDATE +#define ENGINE_load_private_key ENGINE_LOAD_PRIVATE_KEY +#define ENGINE_set_default ENGINE_SET_DEFAULT +#define ERR_clear_error ERR_CLEAR_ERROR +#define ERR_error_string ERR_ERROR_STRING +#define ERR_error_string_n ERR_ERROR_STRING_N +#define ERR_free_strings ERR_FREE_STRINGS +#define ERR_get_error ERR_GET_ERROR +#define ERR_peek_error ERR_PEEK_ERROR +#define ERR_remove_state ERR_REMOVE_STATE +#define EVP_PKEY_copy_parameters EVP_PKEY_COPY_PARAMETERS +#define EVP_PKEY_free EVP_PKEY_FREE +#define EVP_cleanup EVP_CLEANUP +#define GENERAL_NAMES_free GENERAL_NAMES_FREE +#define i2d_X509_PUBKEY I2D_X509_PUBKEY +#define MD4_Final MD4_FINAL +#define MD4_Init MD4_INIT +#define MD4_Update MD4_UPDATE +#define MD5_Final MD5_FINAL +#define MD5_Init MD5_INIT +#define MD5_Update MD5_UPDATE #define OPENSSL_add_all_algo_noconf OPENSSL_ADD_ALL_ALGO_NOCONF #ifndef __VAX #define OPENSSL_load_builtin_modules OPENSSL_LOAD_BUILTIN_MODULES #endif -#define PEM_read_X509 PEM_READ_X509 -#define PEM_write_bio_X509 PEM_WRITE_BIO_X509 -#define PKCS12_PBE_add PKCS12_PBE_ADD -#define PKCS12_free PKCS12_FREE -#define PKCS12_parse PKCS12_PARSE -#define RAND_add RAND_ADD -#define RAND_bytes RAND_BYTES -#define RAND_file_name RAND_FILE_NAME -#define RAND_load_file RAND_LOAD_FILE -#define RAND_status RAND_STATUS -#define SSL_CIPHER_get_name SSL_CIPHER_GET_NAME -#define SSL_CTX_add_client_CA SSL_CTX_ADD_CLIENT_CA -#define SSL_CTX_callback_ctrl SSL_CTX_CALLBACK_CTRL -#define SSL_CTX_check_private_key SSL_CTX_CHECK_PRIVATE_KEY -#define SSL_CTX_ctrl SSL_CTX_CTRL -#define SSL_CTX_free SSL_CTX_FREE -#define SSL_CTX_get_cert_store SSL_CTX_GET_CERT_STORE -#define SSL_CTX_load_verify_locations SSL_CTX_LOAD_VERIFY_LOCATIONS -#define SSL_CTX_new SSL_CTX_NEW -#define SSL_CTX_set_cipher_list SSL_CTX_SET_CIPHER_LIST -#define SSL_CTX_set_def_passwd_cb_ud SSL_CTX_SET_DEF_PASSWD_CB_UD -#define SSL_CTX_set_default_passwd_cb SSL_CTX_SET_DEFAULT_PASSWD_CB -#define SSL_CTX_set_msg_callback SSL_CTX_SET_MSG_CALLBACK -#define SSL_CTX_set_verify SSL_CTX_SET_VERIFY -#define SSL_CTX_use_PrivateKey SSL_CTX_USE_PRIVATEKEY -#define SSL_CTX_use_PrivateKey_file SSL_CTX_USE_PRIVATEKEY_FILE -#define SSL_CTX_use_cert_chain_file SSL_CTX_USE_CERT_CHAIN_FILE -#define SSL_CTX_use_certificate SSL_CTX_USE_CERTIFICATE -#define SSL_CTX_use_certificate_file SSL_CTX_USE_CERTIFICATE_FILE -#define SSL_SESSION_free SSL_SESSION_FREE -#define SSL_connect SSL_CONNECT -#define SSL_free SSL_FREE -#define SSL_get1_session SSL_GET1_SESSION -#define SSL_get_certificate SSL_GET_CERTIFICATE -#define SSL_get_current_cipher SSL_GET_CURRENT_CIPHER -#define SSL_get_error SSL_GET_ERROR -#define SSL_get_peer_cert_chain SSL_GET_PEER_CERT_CHAIN -#define SSL_get_peer_certificate SSL_GET_PEER_CERTIFICATE -#define SSL_get_privatekey SSL_GET_PRIVATEKEY -#define SSL_get_session SSL_GET_SESSION -#define SSL_get_shutdown SSL_GET_SHUTDOWN -#define SSL_get_verify_result SSL_GET_VERIFY_RESULT -#define SSL_library_init SSL_LIBRARY_INIT -#define SSL_load_error_strings SSL_LOAD_ERROR_STRINGS -#define SSL_new SSL_NEW -#define SSL_peek SSL_PEEK -#define SSL_pending SSL_PENDING -#define SSL_read SSL_READ -#define SSL_set_connect_state SSL_SET_CONNECT_STATE -#define SSL_set_fd SSL_SET_FD -#define SSL_set_session SSL_SET_SESSION -#define SSL_shutdown SSL_SHUTDOWN -#define SSL_version SSL_VERSION -#define SSL_write SSL_WRITE -#define SSLeay SSLEAY -#define SSLv23_client_method SSLV23_CLIENT_METHOD -#define SSLv3_client_method SSLV3_CLIENT_METHOD -#define TLSv1_client_method TLSV1_CLIENT_METHOD -#define UI_create_method UI_CREATE_METHOD -#define UI_destroy_method UI_DESTROY_METHOD -#define UI_get0_user_data UI_GET0_USER_DATA -#define UI_get_input_flags UI_GET_INPUT_FLAGS -#define UI_get_string_type UI_GET_STRING_TYPE -#define UI_create_method UI_CREATE_METHOD -#define UI_destroy_method UI_DESTROY_METHOD -#define UI_method_get_closer UI_METHOD_GET_CLOSER -#define UI_method_get_opener UI_METHOD_GET_OPENER -#define UI_method_get_reader UI_METHOD_GET_READER -#define UI_method_get_writer UI_METHOD_GET_WRITER -#define UI_method_set_closer UI_METHOD_SET_CLOSER -#define UI_method_set_opener UI_METHOD_SET_OPENER -#define UI_method_set_reader UI_METHOD_SET_READER -#define UI_method_set_writer UI_METHOD_SET_WRITER -#define UI_OpenSSL UI_OPENSSL -#define UI_set_result UI_SET_RESULT -#define X509V3_EXT_print X509V3_EXT_PRINT -#define X509_EXTENSION_get_critical X509_EXTENSION_GET_CRITICAL -#define X509_EXTENSION_get_data X509_EXTENSION_GET_DATA -#define X509_EXTENSION_get_object X509_EXTENSION_GET_OBJECT -#define X509_LOOKUP_file X509_LOOKUP_FILE -#define X509_NAME_ENTRY_get_data X509_NAME_ENTRY_GET_DATA -#define X509_NAME_get_entry X509_NAME_GET_ENTRY -#define X509_NAME_get_index_by_NID X509_NAME_GET_INDEX_BY_NID -#define X509_NAME_print_ex X509_NAME_PRINT_EX +#define PEM_read_X509 PEM_READ_X509 +#define PEM_write_bio_X509 PEM_WRITE_BIO_X509 +#define PKCS12_free PKCS12_FREE +#define PKCS12_parse PKCS12_PARSE +#define RAND_add RAND_ADD +#define RAND_bytes RAND_BYTES +#define RAND_file_name RAND_FILE_NAME +#define RAND_load_file RAND_LOAD_FILE +#define RAND_status RAND_STATUS +#define SSL_CIPHER_get_name SSL_CIPHER_GET_NAME +#define SSL_CTX_add_client_CA SSL_CTX_ADD_CLIENT_CA +#define SSL_CTX_callback_ctrl SSL_CTX_CALLBACK_CTRL +#define SSL_CTX_check_private_key SSL_CTX_CHECK_PRIVATE_KEY +#define SSL_CTX_ctrl SSL_CTX_CTRL +#define SSL_CTX_free SSL_CTX_FREE +#define SSL_CTX_get_cert_store SSL_CTX_GET_CERT_STORE +#define SSL_CTX_load_verify_locations SSL_CTX_LOAD_VERIFY_LOCATIONS +#define SSL_CTX_new SSL_CTX_NEW +#define SSL_CTX_set_cipher_list SSL_CTX_SET_CIPHER_LIST +#define SSL_CTX_set_def_passwd_cb_ud SSL_CTX_SET_DEF_PASSWD_CB_UD +#define SSL_CTX_set_default_passwd_cb SSL_CTX_SET_DEFAULT_PASSWD_CB +#define SSL_CTX_set_msg_callback SSL_CTX_SET_MSG_CALLBACK +#define SSL_CTX_set_verify SSL_CTX_SET_VERIFY +#define SSL_CTX_use_PrivateKey SSL_CTX_USE_PRIVATEKEY +#define SSL_CTX_use_PrivateKey_file SSL_CTX_USE_PRIVATEKEY_FILE +#define SSL_CTX_use_cert_chain_file SSL_CTX_USE_CERT_CHAIN_FILE +#define SSL_CTX_use_certificate SSL_CTX_USE_CERTIFICATE +#define SSL_CTX_use_certificate_file SSL_CTX_USE_CERTIFICATE_FILE +#define SSL_SESSION_free SSL_SESSION_FREE +#define SSL_connect SSL_CONNECT +#define SSL_free SSL_FREE +#define SSL_get1_session SSL_GET1_SESSION +#define SSL_get_certificate SSL_GET_CERTIFICATE +#define SSL_get_current_cipher SSL_GET_CURRENT_CIPHER +#define SSL_get_error SSL_GET_ERROR +#define SSL_get_peer_cert_chain SSL_GET_PEER_CERT_CHAIN +#define SSL_get_peer_certificate SSL_GET_PEER_CERTIFICATE +#define SSL_get_privatekey SSL_GET_PRIVATEKEY +#define SSL_get_session SSL_GET_SESSION +#define SSL_get_shutdown SSL_GET_SHUTDOWN +#define SSL_get_verify_result SSL_GET_VERIFY_RESULT +#define SSL_library_init SSL_LIBRARY_INIT +#define SSL_load_error_strings SSL_LOAD_ERROR_STRINGS +#define SSL_new SSL_NEW +#define SSL_peek SSL_PEEK +#define SSL_pending SSL_PENDING +#define SSL_read SSL_READ +#define SSL_set_connect_state SSL_SET_CONNECT_STATE +#define SSL_set_fd SSL_SET_FD +#define SSL_set_session SSL_SET_SESSION +#define SSL_shutdown SSL_SHUTDOWN +#define SSL_version SSL_VERSION +#define SSL_write SSL_WRITE +#define SSLeay SSLEAY +#define SSLv23_client_method SSLV23_CLIENT_METHOD +#define SSLv3_client_method SSLV3_CLIENT_METHOD +#define TLSv1_client_method TLSV1_CLIENT_METHOD +#define UI_create_method UI_CREATE_METHOD +#define UI_destroy_method UI_DESTROY_METHOD +#define UI_get0_user_data UI_GET0_USER_DATA +#define UI_get_input_flags UI_GET_INPUT_FLAGS +#define UI_get_string_type UI_GET_STRING_TYPE +#define UI_create_method UI_CREATE_METHOD +#define UI_destroy_method UI_DESTROY_METHOD +#define UI_method_get_closer UI_METHOD_GET_CLOSER +#define UI_method_get_opener UI_METHOD_GET_OPENER +#define UI_method_get_reader UI_METHOD_GET_READER +#define UI_method_get_writer UI_METHOD_GET_WRITER +#define UI_method_set_closer UI_METHOD_SET_CLOSER +#define UI_method_set_opener UI_METHOD_SET_OPENER +#define UI_method_set_reader UI_METHOD_SET_READER +#define UI_method_set_writer UI_METHOD_SET_WRITER +#define UI_OpenSSL UI_OPENSSL +#define UI_set_result UI_SET_RESULT +#define X509V3_EXT_print X509V3_EXT_PRINT +#define X509_EXTENSION_get_critical X509_EXTENSION_GET_CRITICAL +#define X509_EXTENSION_get_data X509_EXTENSION_GET_DATA +#define X509_EXTENSION_get_object X509_EXTENSION_GET_OBJECT +#define X509_LOOKUP_file X509_LOOKUP_FILE +#define X509_NAME_ENTRY_get_data X509_NAME_ENTRY_GET_DATA +#define X509_NAME_get_entry X509_NAME_GET_ENTRY +#define X509_NAME_get_index_by_NID X509_NAME_GET_INDEX_BY_NID +#define X509_NAME_print_ex X509_NAME_PRINT_EX #define X509_STORE_CTX_get_current_cert X509_STORE_CTX_GET_CURRENT_CERT -#define X509_STORE_add_lookup X509_STORE_ADD_LOOKUP -#define X509_STORE_set_flags X509_STORE_SET_FLAGS -#define X509_check_issued X509_CHECK_ISSUED -#define X509_free X509_FREE -#define X509_get_ext_d2i X509_GET_EXT_D2I -#define X509_get_issuer_name X509_GET_ISSUER_NAME -#define X509_get_pubkey X509_GET_PUBKEY -#define X509_get_serialNumber X509_GET_SERIALNUMBER -#define X509_get_subject_name X509_GET_SUBJECT_NAME -#define X509_load_crl_file X509_LOAD_CRL_FILE -#define X509_verify_cert_error_string X509_VERIFY_CERT_ERROR_STRING -#define d2i_PKCS12_fp D2I_PKCS12_FP -#define i2t_ASN1_OBJECT I2T_ASN1_OBJECT -#define sk_num SK_NUM -#define sk_pop SK_POP -#define sk_pop_free SK_POP_FREE -#define sk_value SK_VALUE +#define X509_STORE_add_lookup X509_STORE_ADD_LOOKUP +#define X509_STORE_set_flags X509_STORE_SET_FLAGS +#define X509_check_issued X509_CHECK_ISSUED +#define X509_free X509_FREE +#define X509_get_ext_d2i X509_GET_EXT_D2I +#define X509_get_issuer_name X509_GET_ISSUER_NAME +#define X509_get_pubkey X509_GET_PUBKEY +#define X509_get_serialNumber X509_GET_SERIALNUMBER +#define X509_get_subject_name X509_GET_SUBJECT_NAME +#define X509_load_crl_file X509_LOAD_CRL_FILE +#define X509_verify_cert_error_string X509_VERIFY_CERT_ERROR_STRING +#define d2i_PKCS12_fp D2I_PKCS12_FP +#define i2t_ASN1_OBJECT I2T_ASN1_OBJECT +#define sk_num SK_NUM +#define sk_pop SK_POP +#define sk_pop_free SK_POP_FREE +#define sk_value SK_VALUE #ifdef __VAX #define OPENSSL_NO_SHA256 #endif -#define SHA256_Final SHA256_FINAL -#define SHA256_Init SHA256_INIT +#define SHA256_Final SHA256_FINAL +#define SHA256_Init SHA256_INIT #define SHA256_Update SHA256_UPDATE #define USE_UPPERCASE_GSSAPI 1 -#define gss_seal GSS_SEAL -#define gss_unseal GSS_UNSEAL +#define gss_seal GSS_SEAL +#define gss_unseal GSS_UNSEAL #define USE_UPPERCASE_KRBAPI 1 @@ -380,11 +378,11 @@ static struct passwd *vms_getpwuid(uid_t uid) /* VAX symbols are always in uppercase */ #ifdef __VAX -#define inflate INFLATE -#define inflateEnd INFLATEEND +#define inflate INFLATE +#define inflateEnd INFLATEEND #define inflateInit2_ INFLATEINIT2_ -#define inflateInit_ INFLATEINIT_ -#define zlibVersion ZLIBVERSION +#define inflateInit_ INFLATEINIT_ +#define zlibVersion ZLIBVERSION #endif /* Older VAX OpenSSL port defines these as Macros */ @@ -392,11 +390,11 @@ static struct passwd *vms_getpwuid(uid_t uid) /* that way a newer port will also work if some one has one */ #ifdef __VAX -# include -# ifndef OpenSSL_add_all_algorithms -# define OpenSSL_add_all_algorithms OPENSSL_ADD_ALL_ALGORITHMS - void OPENSSL_ADD_ALL_ALGORITHMS(void); -# endif +# include +# ifndef OpenSSL_add_all_algorithms +# define OpenSSL_add_all_algorithms OPENSSL_ADD_ALL_ALGORITHMS + void OPENSSL_ADD_ALL_ALGORITHMS(void); +# endif #endif #endif /* HEADER_CURL_SETUP_VMS_H */ diff --git a/lib/sha256.c b/lib/sha256.c index 2d0357189a0e..b653100d5dd4 100644 --- a/lib/sha256.c +++ b/lib/sha256.c @@ -28,20 +28,25 @@ #if !defined(CURL_DISABLE_AWS) || !defined(CURL_DISABLE_DIGEST_AUTH) || \ defined(USE_LIBSSH2) || defined(USE_SSL) -#include "curlx/warnless.h" #include "curl_sha256.h" -#include "curl_hmac.h" + +#ifdef USE_MBEDTLS + #include + #if MBEDTLS_VERSION_NUMBER < 0x03020000 + #error "mbedTLS 3.2.0 or later required" + #endif + #include + #if defined(PSA_WANT_ALG_SHA_256) && PSA_WANT_ALG_SHA_256 /* mbedTLS 4+ */ + #define USE_MBEDTLS_SHA256 + #endif +#endif #ifdef USE_OPENSSL #include #elif defined(USE_GNUTLS) #include -#elif defined(USE_MBEDTLS) -#include -#if MBEDTLS_VERSION_NUMBER < 0x03020000 - #error "mbedTLS 3.2.0 or later required" -#endif -#include +#elif defined(USE_MBEDTLS_SHA256) +#include #elif (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && \ (__MAC_OS_X_VERSION_MAX_ALLOWED >= 1040)) || \ (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \ @@ -52,10 +57,6 @@ #include #endif -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - /* Please keep the SSL backend-specific #if branches in this order: * * 1. USE_OPENSSL @@ -126,13 +127,15 @@ static void my_sha256_final(unsigned char *digest, void *ctx) sha256_digest(ctx, SHA256_DIGEST_SIZE, digest); } -#elif defined(USE_MBEDTLS) +#elif defined(USE_MBEDTLS_SHA256) -typedef mbedtls_sha256_context my_sha256_ctx; +typedef psa_hash_operation_t my_sha256_ctx; static CURLcode my_sha256_init(void *ctx) { - (void)mbedtls_sha256_starts(ctx, 0); + memset(ctx, 0, sizeof(my_sha256_ctx)); + if(psa_hash_setup(ctx, PSA_ALG_SHA_256) != PSA_SUCCESS) + return CURLE_OUT_OF_MEMORY; return CURLE_OK; } @@ -140,12 +143,14 @@ static void my_sha256_update(void *ctx, const unsigned char *data, unsigned int length) { - (void)mbedtls_sha256_update(ctx, data, length); + (void)psa_hash_update(ctx, data, length); } static void my_sha256_final(unsigned char *digest, void *ctx) { - (void)mbedtls_sha256_finish(ctx, digest); + size_t actual_length; + (void)psa_hash_finish(ctx, digest, CURL_SHA256_DIGEST_LENGTH, + &actual_length); } #elif defined(AN_APPLE_OS) @@ -186,7 +191,7 @@ static CURLcode my_sha256_init(void *in) { my_sha256_ctx *ctx = (my_sha256_ctx *)in; if(!CryptAcquireContext(&ctx->hCryptProv, NULL, NULL, PROV_RSA_AES, - CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) + CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) return CURLE_OUT_OF_MEMORY; if(!CryptCreateHash(ctx->hCryptProv, CALG_SHA_256, 0, 0, &ctx->hHash)) { @@ -203,11 +208,7 @@ static void my_sha256_update(void *in, unsigned int length) { my_sha256_ctx *ctx = (my_sha256_ctx *)in; -#ifdef __MINGW32CE__ - CryptHashData(ctx->hHash, (BYTE *)CURL_UNCONST(data), length, 0); -#else CryptHashData(ctx->hHash, (const BYTE *)data, length, 0); -#endif } static void my_sha256_final(unsigned char *digest, void *in) @@ -233,42 +234,43 @@ static void my_sha256_final(unsigned char *digest, void *in) /* This is based on the SHA256 implementation in LibTomCrypt that was released * into public domain. */ -#define WPA_GET_BE32(a) ((((unsigned long)(a)[0]) << 24) | \ - (((unsigned long)(a)[1]) << 16) | \ - (((unsigned long)(a)[2]) << 8) | \ - ((unsigned long)(a)[3])) -#define WPA_PUT_BE32(a, val) \ -do { \ - (a)[0] = (unsigned char)((((unsigned long) (val)) >> 24) & 0xff); \ - (a)[1] = (unsigned char)((((unsigned long) (val)) >> 16) & 0xff); \ - (a)[2] = (unsigned char)((((unsigned long) (val)) >> 8) & 0xff); \ - (a)[3] = (unsigned char)(((unsigned long) (val)) & 0xff); \ -} while(0) +#define WPA_GET_BE32(a) \ + ((((unsigned long)(a)[0]) << 24) | \ + (((unsigned long)(a)[1]) << 16) | \ + (((unsigned long)(a)[2]) << 8) | \ + ((unsigned long)(a)[3])) +#define WPA_PUT_BE32(a, val) \ + do { \ + (a)[0] = (unsigned char)((((unsigned long)(val)) >> 24) & 0xff); \ + (a)[1] = (unsigned char)((((unsigned long)(val)) >> 16) & 0xff); \ + (a)[2] = (unsigned char)((((unsigned long)(val)) >> 8) & 0xff); \ + (a)[3] = (unsigned char) (((unsigned long)(val)) & 0xff); \ + } while(0) #ifdef HAVE_LONGLONG -#define WPA_PUT_BE64(a, val) \ -do { \ - (a)[0] = (unsigned char)(((unsigned long long)(val)) >> 56); \ - (a)[1] = (unsigned char)(((unsigned long long)(val)) >> 48); \ - (a)[2] = (unsigned char)(((unsigned long long)(val)) >> 40); \ - (a)[3] = (unsigned char)(((unsigned long long)(val)) >> 32); \ - (a)[4] = (unsigned char)(((unsigned long long)(val)) >> 24); \ - (a)[5] = (unsigned char)(((unsigned long long)(val)) >> 16); \ - (a)[6] = (unsigned char)(((unsigned long long)(val)) >> 8); \ - (a)[7] = (unsigned char)(((unsigned long long)(val)) & 0xff); \ -} while(0) +#define WPA_PUT_BE64(a, val) \ + do { \ + (a)[0] = (unsigned char)(((unsigned long long)(val)) >> 56); \ + (a)[1] = (unsigned char)(((unsigned long long)(val)) >> 48); \ + (a)[2] = (unsigned char)(((unsigned long long)(val)) >> 40); \ + (a)[3] = (unsigned char)(((unsigned long long)(val)) >> 32); \ + (a)[4] = (unsigned char)(((unsigned long long)(val)) >> 24); \ + (a)[5] = (unsigned char)(((unsigned long long)(val)) >> 16); \ + (a)[6] = (unsigned char)(((unsigned long long)(val)) >> 8); \ + (a)[7] = (unsigned char)(((unsigned long long)(val)) & 0xff); \ + } while(0) #else -#define WPA_PUT_BE64(a, val) \ -do { \ - (a)[0] = (unsigned char)(((unsigned __int64)(val)) >> 56); \ - (a)[1] = (unsigned char)(((unsigned __int64)(val)) >> 48); \ - (a)[2] = (unsigned char)(((unsigned __int64)(val)) >> 40); \ - (a)[3] = (unsigned char)(((unsigned __int64)(val)) >> 32); \ - (a)[4] = (unsigned char)(((unsigned __int64)(val)) >> 24); \ - (a)[5] = (unsigned char)(((unsigned __int64)(val)) >> 16); \ - (a)[6] = (unsigned char)(((unsigned __int64)(val)) >> 8); \ - (a)[7] = (unsigned char)(((unsigned __int64)(val)) & 0xff); \ -} while(0) +#define WPA_PUT_BE64(a, val) \ + do { \ + (a)[0] = (unsigned char)(((unsigned __int64)(val)) >> 56); \ + (a)[1] = (unsigned char)(((unsigned __int64)(val)) >> 48); \ + (a)[2] = (unsigned char)(((unsigned __int64)(val)) >> 40); \ + (a)[3] = (unsigned char)(((unsigned __int64)(val)) >> 32); \ + (a)[4] = (unsigned char)(((unsigned __int64)(val)) >> 24); \ + (a)[5] = (unsigned char)(((unsigned __int64)(val)) >> 16); \ + (a)[6] = (unsigned char)(((unsigned __int64)(val)) >> 8); \ + (a)[7] = (unsigned char)(((unsigned __int64)(val)) & 0xff); \ + } while(0) #endif struct sha256_state { @@ -301,20 +303,21 @@ static const unsigned long K[64] = { /* Various logical functions */ #define RORc(x, y) \ -(((((unsigned long)(x) & 0xFFFFFFFFUL) >> (unsigned long)((y) & 31)) | \ - ((unsigned long)(x) << (unsigned long)(32 - ((y) & 31)))) & 0xFFFFFFFFUL) -#define Sha256_Ch(x,y,z) (z ^ (x & (y ^ z))) -#define Sha256_Maj(x,y,z) (((x | y) & z) | (x & y)) -#define Sha256_S(x, n) RORc((x), (n)) -#define Sha256_R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) + (((((unsigned long)(x) & 0xFFFFFFFFUL) >> (unsigned long)((y) & 31)) | \ + ((unsigned long)(x) << (unsigned long)(32 - ((y) & 31)))) & 0xFFFFFFFFUL) + +#define Sha256_Ch(x, y, z) (z ^ (x & (y ^ z))) +#define Sha256_Maj(x, y, z) (((x | y) & z) | (x & y)) +#define Sha256_S(x, n) RORc((x), (n)) +#define Sha256_R(x, n) (((x) & 0xFFFFFFFFUL) >> (n)) + #define Sigma0(x) (Sha256_S(x, 2) ^ Sha256_S(x, 13) ^ Sha256_S(x, 22)) #define Sigma1(x) (Sha256_S(x, 6) ^ Sha256_S(x, 11) ^ Sha256_S(x, 25)) #define Gamma0(x) (Sha256_S(x, 7) ^ Sha256_S(x, 18) ^ Sha256_R(x, 3)) #define Gamma1(x) (Sha256_S(x, 17) ^ Sha256_S(x, 19) ^ Sha256_R(x, 10)) /* Compress 512-bits */ -static int sha256_compress(struct sha256_state *md, - const unsigned char *buf) +static int sha256_compress(struct sha256_state *md, const unsigned char *buf) { unsigned long S[8], W[64]; int i; @@ -328,12 +331,11 @@ static int sha256_compress(struct sha256_state *md, W[i] = WPA_GET_BE32(buf + (4 * i)); /* fill W[16..63] */ for(i = 16; i < 64; i++) { - W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + - W[i - 16]; + W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) + W[i - 16]; } /* Compress */ -#define RND(a,b,c,d,e,f,g,h,i) \ +#define RND(a, b, c, d, e, f, g, h, i) \ do { \ unsigned long t0 = h + Sigma1(e) + Sha256_Ch(e, f, g) + K[i] + W[i]; \ unsigned long t1 = Sigma0(a) + Sha256_Maj(a, b, c); \ @@ -344,8 +346,15 @@ static int sha256_compress(struct sha256_state *md, for(i = 0; i < 64; ++i) { unsigned long t; RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i); - t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; - S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; + t = S[7]; + S[7] = S[6]; + S[6] = S[5]; + S[5] = S[4]; + S[4] = S[3]; + S[3] = S[2]; + S[2] = S[1]; + S[1] = S[0]; + S[0] = t; } /* Feedback */ @@ -489,7 +498,6 @@ CURLcode Curl_sha256it(unsigned char *output, const unsigned char *input, return result; } - const struct HMAC_params Curl_HMAC_SHA256 = { my_sha256_init, /* Hash initialization function. */ my_sha256_update, /* Hash update function. */ diff --git a/lib/sigpipe.h b/lib/sigpipe.h index 1be3a111e958..5d2c78a2713c 100644 --- a/lib/sigpipe.h +++ b/lib/sigpipe.h @@ -25,7 +25,7 @@ ***************************************************************************/ #include "curl_setup.h" -#if defined(HAVE_SIGACTION) && \ +#if defined(HAVE_SIGACTION) && \ (defined(USE_OPENSSL) || defined(USE_MBEDTLS) || defined(USE_WOLFSSL)) #include @@ -88,12 +88,12 @@ static void sigpipe_apply(struct Curl_easy *data, #else /* for systems without sigaction */ -#define sigpipe_ignore(x,y) Curl_nop_stmt -#define sigpipe_apply(x,y) Curl_nop_stmt -#define sigpipe_init(x) Curl_nop_stmt -#define sigpipe_restore(x) Curl_nop_stmt +#define sigpipe_ignore(x, y) Curl_nop_stmt +#define sigpipe_apply(x, y) Curl_nop_stmt +#define sigpipe_init(x) Curl_nop_stmt +#define sigpipe_restore(x) Curl_nop_stmt #define SIGPIPE_VARIABLE(x) -#define SIGPIPE_MEMBER(x) bool x +#define SIGPIPE_MEMBER(x) bool x #endif #endif /* HEADER_CURL_SIGPIPE_H */ diff --git a/lib/slist.c b/lib/slist.c index 366b24760959..3be71cb728dd 100644 --- a/lib/slist.c +++ b/lib/slist.c @@ -24,18 +24,12 @@ #include "curl_setup.h" -#include - #include "slist.h" -/* The last #include files should be: */ -#include "curl_memory.h" -#include "memdebug.h" - /* returns last node in linked list */ static struct curl_slist *slist_get_last(struct curl_slist *list) { - struct curl_slist *item; + struct curl_slist *item; /* if caller passed us a NULL, return now */ if(!list) @@ -58,19 +52,20 @@ static struct curl_slist *slist_get_last(struct curl_slist *list) * If an error occurs, NULL is returned and the string argument is NOT * released. */ -struct curl_slist *Curl_slist_append_nodup(struct curl_slist *list, char *data) +struct curl_slist *Curl_slist_append_nodup(struct curl_slist *list, + const char *data) { - struct curl_slist *last; - struct curl_slist *new_item; + struct curl_slist *last; + struct curl_slist *new_item; DEBUGASSERT(data); - new_item = malloc(sizeof(struct curl_slist)); + new_item = curlx_malloc(sizeof(struct curl_slist)); if(!new_item) return NULL; new_item->next = NULL; - new_item->data = data; + new_item->data = CURL_UNCONST(data); /* if this is the first item, then new_item *is* the list */ if(!list) @@ -88,17 +83,16 @@ struct curl_slist *Curl_slist_append_nodup(struct curl_slist *list, char *data) * bothersome, then simply create a separate _init function and call it * appropriately from within the program. */ -struct curl_slist *curl_slist_append(struct curl_slist *list, - const char *data) +struct curl_slist *curl_slist_append(struct curl_slist *list, const char *data) { - char *dupdata = strdup(data); + char *dupdata = curlx_strdup(data); if(!dupdata) return NULL; list = Curl_slist_append_nodup(list, dupdata); if(!list) - free(dupdata); + curlx_free(dupdata); return list; } @@ -130,8 +124,8 @@ struct curl_slist *Curl_slist_duplicate(struct curl_slist *inlist) /* be nice and clean up resources */ void curl_slist_free_all(struct curl_slist *list) { - struct curl_slist *next; - struct curl_slist *item; + struct curl_slist *next; + struct curl_slist *item; if(!list) return; @@ -140,7 +134,7 @@ void curl_slist_free_all(struct curl_slist *list) do { next = item->next; Curl_safefree(item->data); - free(item); + curlx_free(item); item = next; } while(next); } diff --git a/lib/slist.h b/lib/slist.h index 9561fd022686..47a30824db01 100644 --- a/lib/slist.h +++ b/lib/slist.h @@ -36,6 +36,6 @@ struct curl_slist *Curl_slist_duplicate(struct curl_slist *inlist); * it to the list. */ struct curl_slist *Curl_slist_append_nodup(struct curl_slist *list, - char *data); + const char *data); #endif /* HEADER_CURL_SLIST_H */ diff --git a/lib/smb.c b/lib/smb.c index 2aa8e96644a9..5f3e419a420b 100644 --- a/lib/smb.c +++ b/lib/smb.c @@ -31,21 +31,16 @@ #include "urldata.h" #include "url.h" #include "sendf.h" -#include "multiif.h" +#include "curl_trc.h" #include "cfilters.h" #include "connect.h" #include "progress.h" #include "transfer.h" #include "select.h" -#include "vtls/vtls.h" #include "curl_ntlm_core.h" #include "escape.h" #include "curl_endian.h" - -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - +#include "curlx/strcopy.h" /* meta key for storing protocol meta at easy handle */ #define CURL_META_SMB_EASY "meta:proto:smb:easy" @@ -329,7 +324,7 @@ const struct Curl_handler Curl_handler_smb = { PORT_SMB, /* defport */ CURLPROTO_SMB, /* protocol */ CURLPROTO_SMB, /* family */ - PROTOPT_NONE /* flags */ + PROTOPT_CONN_REUSE /* flags */ }; #ifdef USE_SSL @@ -358,7 +353,7 @@ const struct Curl_handler Curl_handler_smbs = { PORT_SMBS, /* defport */ CURLPROTO_SMBS, /* protocol */ CURLPROTO_SMB, /* family */ - PROTOPT_SSL /* flags */ + PROTOPT_SSL | PROTOPT_CONN_REUSE /* flags */ }; #endif @@ -372,7 +367,7 @@ const struct Curl_handler Curl_handler_smbs = { defined(__OS400__) static unsigned short smb_swap16(unsigned short x) { - return (unsigned short) ((x << 8) | ((x >> 8) & 0xff)); + return (unsigned short)((x << 8) | ((x >> 8) & 0xff)); } static unsigned int smb_swap32(unsigned int x) @@ -383,8 +378,8 @@ static unsigned int smb_swap32(unsigned int x) static curl_off_t smb_swap64(curl_off_t x) { - return ((curl_off_t) smb_swap32((unsigned int) x) << 32) | - smb_swap32((unsigned int) (x >> 32)); + return ((curl_off_t)smb_swap32((unsigned int)x) << 32) | + smb_swap32((unsigned int)(x >> 32)); } #else @@ -451,7 +446,7 @@ static void smb_easy_dtor(void *key, size_t klen, void *entry) /* `req->path` points to somewhere in `struct smb_conn` which is * kept at the connection meta. If the connection is destroyed first, * req->path points to free'd memory. */ - free(req); + curlx_free(req); } static void smb_conn_dtor(void *key, size_t klen, void *entry) @@ -463,7 +458,7 @@ static void smb_conn_dtor(void *key, size_t klen, void *entry) Curl_safefree(smbc->domain); Curl_safefree(smbc->recv_buf); Curl_safefree(smbc->send_buf); - free(smbc); + curlx_free(smbc); } /* this should setup things in the connection, not in the easy @@ -475,13 +470,13 @@ static CURLcode smb_setup_connection(struct Curl_easy *data, struct smb_request *req; /* Initialize the connection state */ - smbc = calloc(1, sizeof(*smbc)); + smbc = curlx_calloc(1, sizeof(*smbc)); if(!smbc || Curl_conn_meta_set(conn, CURL_META_SMB_CONN, smbc, smb_conn_dtor)) return CURLE_OUT_OF_MEMORY; /* Initialize the request state */ - req = calloc(1, sizeof(*req)); + req = curlx_calloc(1, sizeof(*req)); if(!req || Curl_meta_set(data, CURL_META_SMB_EASY, req, smb_easy_dtor)) return CURLE_OUT_OF_MEMORY; @@ -506,16 +501,13 @@ static CURLcode smb_connect(struct Curl_easy *data, bool *done) /* Initialize the connection state */ smbc->state = SMB_CONNECTING; - smbc->recv_buf = malloc(MAX_MESSAGE_SIZE); + smbc->recv_buf = curlx_malloc(MAX_MESSAGE_SIZE); if(!smbc->recv_buf) return CURLE_OUT_OF_MEMORY; - smbc->send_buf = malloc(MAX_MESSAGE_SIZE); + smbc->send_buf = curlx_malloc(MAX_MESSAGE_SIZE); if(!smbc->send_buf) return CURLE_OUT_OF_MEMORY; - /* Multiple requests are allowed with this connection */ - connkeep(conn, "SMB default"); - /* Parse the username, domain, and password */ slash = strchr(conn->user, '/'); if(!slash) @@ -523,14 +515,14 @@ static CURLcode smb_connect(struct Curl_easy *data, bool *done) if(slash) { smbc->user = slash + 1; - smbc->domain = strdup(conn->user); + smbc->domain = curlx_strdup(conn->user); if(!smbc->domain) return CURLE_OUT_OF_MEMORY; smbc->domain[slash - conn->user] = 0; } else { smbc->user = conn->user; - smbc->domain = strdup(conn->host.name); + smbc->domain = curlx_strdup(conn->host.name); if(!smbc->domain) return CURLE_OUT_OF_MEMORY; } @@ -580,7 +572,7 @@ static CURLcode smb_recv_message(struct Curl_easy *data, if(nbt_size >= msg_size + 1) { /* Add the word count */ - msg_size += 1 + ((unsigned char) buf[msg_size]) * sizeof(unsigned short); + msg_size += 1 + ((unsigned char)buf[msg_size]) * sizeof(unsigned short); if(nbt_size >= msg_size + sizeof(unsigned short)) { /* Add the byte count */ msg_size += sizeof(unsigned short) + @@ -608,8 +600,8 @@ static void smb_format_message(struct smb_conn *smbc, const unsigned int pid = 0xbad71d; /* made up */ memset(h, 0, sizeof(*h)); - h->nbt_length = htons((unsigned short) (sizeof(*h) - sizeof(unsigned int) + - len)); + h->nbt_length = htons((unsigned short)(sizeof(*h) - sizeof(unsigned int) + + len)); memcpy((char *)h->magic, "\xffSMB", 4); h->command = cmd; h->flags = SMB_FLAGS_CANONICAL_PATHNAMES | SMB_FLAGS_CASELESS_PATHNAMES; @@ -617,7 +609,7 @@ static void smb_format_message(struct smb_conn *smbc, h->uid = smb_swap16(smbc->uid); h->tid = smb_swap16(req->tid); h->pid_high = smb_swap16((unsigned short)(pid >> 16)); - h->pid = smb_swap16((unsigned short) pid); + h->pid = smb_swap16((unsigned short)pid); } static CURLcode smb_send(struct Curl_easy *data, struct smb_conn *smbc, @@ -668,12 +660,12 @@ static CURLcode smb_send_message(struct Curl_easy *data, unsigned char cmd, const void *msg, size_t msg_len) { - smb_format_message(smbc, req, (struct smb_header *)smbc->send_buf, - cmd, msg_len); - if((sizeof(struct smb_header) + msg_len) > MAX_MESSAGE_SIZE) { + if((MAX_MESSAGE_SIZE - sizeof(struct smb_header)) < msg_len) { DEBUGASSERT(0); return CURLE_SEND_ERROR; } + smb_format_message(smbc, req, (struct smb_header *)smbc->send_buf, + cmd, msg_len); memcpy(smbc->send_buf + sizeof(struct smb_header), msg, msg_len); return smb_send(data, smbc, sizeof(struct smb_header) + msg_len, 0); @@ -797,8 +789,8 @@ static CURLcode smb_send_open(struct Curl_easy *data, msg.access = smb_swap32(SMB_GENERIC_READ); msg.create_disposition = smb_swap32(SMB_FILE_OPEN); } - msg.byte_count = smb_swap16((unsigned short) byte_count); - strcpy(msg.bytes, req->path); + msg.byte_count = smb_swap16((unsigned short)byte_count); + curlx_strcopy(msg.bytes, sizeof(msg.bytes), req->path, byte_count - 1); return smb_send_message(data, smbc, req, SMB_COM_NT_CREATE_ANDX, &msg, sizeof(msg) - sizeof(msg.bytes) + byte_count); @@ -838,8 +830,8 @@ static CURLcode smb_send_read(struct Curl_easy *data, msg.word_count = SMB_WC_READ_ANDX; msg.andx.command = SMB_COM_NO_ANDX_COMMAND; msg.fid = smb_swap16(req->fid); - msg.offset = smb_swap32((unsigned int) offset); - msg.offset_high = smb_swap32((unsigned int) (offset >> 32)); + msg.offset = smb_swap32((unsigned int)offset); + msg.offset_high = smb_swap32((unsigned int)(offset >> 32)); msg.min_bytes = smb_swap16(MAX_PAYLOAD_SIZE); msg.max_bytes = smb_swap16(MAX_PAYLOAD_SIZE); @@ -863,16 +855,16 @@ static CURLcode smb_send_write(struct Curl_easy *data, msg->word_count = SMB_WC_WRITE_ANDX; msg->andx.command = SMB_COM_NO_ANDX_COMMAND; msg->fid = smb_swap16(req->fid); - msg->offset = smb_swap32((unsigned int) offset); - msg->offset_high = smb_swap32((unsigned int) (offset >> 32)); - msg->data_length = smb_swap16((unsigned short) upload_size); + msg->offset = smb_swap32((unsigned int)offset); + msg->offset_high = smb_swap32((unsigned int)(offset >> 32)); + msg->data_length = smb_swap16((unsigned short)upload_size); msg->data_offset = smb_swap16(sizeof(*msg) - sizeof(unsigned int)); - msg->byte_count = smb_swap16((unsigned short) (upload_size + 1)); + msg->byte_count = smb_swap16((unsigned short)(upload_size + 1)); smb_format_message(smbc, req, &msg->h, SMB_COM_WRITE_ANDX, - sizeof(*msg) - sizeof(msg->h) + (size_t) upload_size); + sizeof(*msg) - sizeof(msg->h) + (size_t)upload_size); - return smb_send(data, smbc, sizeof(*msg), (size_t) upload_size); + return smb_send(data, smbc, sizeof(*msg), (size_t)upload_size); } static CURLcode smb_send_and_recv(struct Curl_easy *data, @@ -1021,7 +1013,7 @@ static void get_posix_time(time_t *out, curl_off_t timestamp) *out = TIME_T_MIN; else #endif - *out = (time_t) timestamp; + *out = (time_t)timestamp; } else *out = 0; @@ -1091,7 +1083,7 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done) next_state = SMB_TREE_DISCONNECT; break; } - smb_m = (const struct smb_nt_create_response*) msg; + smb_m = (const struct smb_nt_create_response *)msg; req->fid = smb_swap16(smb_m->fid); data->req.offset = 0; if(data->state.upload) { @@ -1120,9 +1112,9 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done) next_state = SMB_CLOSE; break; } - len = Curl_read16_le(((const unsigned char *) msg) + + len = Curl_read16_le(((const unsigned char *)msg) + sizeof(struct smb_header) + 11); - off = Curl_read16_le(((const unsigned char *) msg) + + off = Curl_read16_le(((const unsigned char *)msg) + sizeof(struct smb_header) + 13); if(len > 0) { if(off + sizeof(unsigned int) + len > smbc->got) { @@ -1149,11 +1141,11 @@ static CURLcode smb_request_state(struct Curl_easy *data, bool *done) next_state = SMB_CLOSE; break; } - len = Curl_read16_le(((const unsigned char *) msg) + + len = Curl_read16_le(((const unsigned char *)msg) + sizeof(struct smb_header) + 5); data->req.bytecount += len; data->req.offset += len; - Curl_pgrsSetUploadCounter(data, data->req.bytecount); + Curl_pgrs_upload_inc(data, len); if(data->req.bytecount >= data->req.size) next_state = SMB_CLOSE; else @@ -1249,8 +1241,9 @@ static CURLcode smb_parse_url_path(struct Curl_easy *data, return result; /* Parse the path for the share */ - smbc->share = strdup((*path == '/' || *path == '\\') ? path + 1 : path); - free(path); + smbc->share = curlx_strdup((*path == '/' || *path == '\\') + ? path + 1 : path); + curlx_free(path); if(!smbc->share) return CURLE_OUT_OF_MEMORY; diff --git a/lib/smtp.c b/lib/smtp.c index 76ed4f280afd..031dcc9bdad6 100644 --- a/lib/smtp.c +++ b/lib/smtp.c @@ -57,34 +57,27 @@ #include #endif -#include #include "urldata.h" #include "sendf.h" +#include "curl_trc.h" #include "hostip.h" #include "progress.h" #include "transfer.h" #include "escape.h" #include "http.h" /* for HTTP proxy tunnel stuff */ #include "mime.h" -#include "socks.h" #include "smtp.h" #include "vtls/vtls.h" #include "cfilters.h" #include "connect.h" #include "select.h" -#include "multiif.h" #include "url.h" #include "curl_gethostname.h" #include "bufref.h" #include "curl_sasl.h" -#include "curlx/warnless.h" #include "idn.h" #include "curlx/strparse.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - /* meta key for storing protocol meta at easy handle */ #define CURL_META_SMTP_EASY "meta:proto:smtp:easy" /* meta key for storing protocol meta at connection */ @@ -205,7 +198,7 @@ const struct Curl_handler Curl_handler_smtp = { CURLPROTO_SMTP, /* protocol */ CURLPROTO_SMTP, /* family */ PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY | /* flags */ - PROTOPT_URLOPTIONS | PROTOPT_SSL_REUSE + PROTOPT_URLOPTIONS | PROTOPT_SSL_REUSE | PROTOPT_CONN_REUSE }; #ifdef USE_SSL @@ -235,8 +228,8 @@ const struct Curl_handler Curl_handler_smtps = { PORT_SMTPS, /* defport */ CURLPROTO_SMTPS, /* protocol */ CURLPROTO_SMTP, /* family */ - PROTOPT_CLOSEACTION | PROTOPT_SSL - | PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS /* flags */ + PROTOPT_CLOSEACTION | PROTOPT_SSL | /* flags */ + PROTOPT_NOURLQUERY | PROTOPT_URLOPTIONS | PROTOPT_CONN_REUSE }; #endif @@ -287,10 +280,10 @@ static bool smtp_endofresp(struct Curl_easy *data, struct connectdata *conn, const char *p = tmpline; result = TRUE; memcpy(tmpline, line, (len == 5 ? 5 : 3)); - tmpline[len == 5 ? 5 : 3 ] = 0; + tmpline[len == 5 ? 5 : 3] = 0; if(curlx_str_number(&p, &code, len == 5 ? 99999 : 999)) return FALSE; - *resp = (int) code; + *resp = (int)code; /* Make sure real server never sends internal value */ if(*resp == 1) @@ -510,7 +503,7 @@ static CURLcode smtp_perform_auth(struct Curl_easy *data, CURLcode result = CURLE_OK; struct smtp_conn *smtpc = Curl_conn_meta_get(data->conn, CURL_META_SMTP_CONN); - const char *ir = (const char *) Curl_bufref_ptr(initresp); + const char *ir = Curl_bufref_ptr(initresp); if(!smtpc) return CURLE_FAILED_INIT; @@ -543,8 +536,7 @@ static CURLcode smtp_continue_auth(struct Curl_easy *data, (void)mech; if(!smtpc) return CURLE_FAILED_INIT; - return Curl_pp_sendf(data, &smtpc->pp, - "%s", (const char *) Curl_bufref_ptr(resp)); + return Curl_pp_sendf(data, &smtpc->pp, "%s", Curl_bufref_ptr(resp)); } /*********************************************************************** @@ -644,7 +636,7 @@ static CURLcode smtp_perform_command(struct Curl_easy *data, utf8 ? " SMTPUTF8" : ""); Curl_free_idnconverted_hostname(&host); - free(address); + curlx_free(address); } else { /* Establish whether we should report that we support SMTPUTF8 for EXPN @@ -720,11 +712,11 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data, worry about that and reply with a 501 error */ from = curl_maprintf("<%s>%s", address, suffix); - free(address); + curlx_free(address); } else /* Null reverse-path, RFC-5321, sect. 3.6.3 */ - from = strdup("<>"); + from = curlx_strdup("<>"); if(!from) { result = CURLE_OUT_OF_MEMORY; @@ -761,11 +753,11 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data, /* An invalid mailbox was provided but we will simply let the server worry about it */ auth = curl_maprintf("<%s>%s", address, suffix); - free(address); + curlx_free(address); } else /* Empty AUTH, RFC-2554, sect. 5 */ - auth = strdup("<>"); + auth = curlx_strdup("<>"); if(!auth) { result = CURLE_OUT_OF_MEMORY; @@ -846,9 +838,9 @@ static CURLcode smtp_perform_mail(struct Curl_easy *data, : ""); /* included in our envelope */ out: - free(from); - free(auth); - free(size); + curlx_free(from); + curlx_free(auth); + curlx_free(size); if(!result) smtp_state(data, smtpc, SMTP_MAIL); @@ -890,7 +882,7 @@ static CURLcode smtp_perform_rcpt_to(struct Curl_easy *data, address, suffix); Curl_free_idnconverted_hostname(&host); - free(address); + curlx_free(address); if(!result) smtp_state(data, smtpc, SMTP_RCPT); @@ -925,7 +917,7 @@ static CURLcode smtp_state_servergreet_resp(struct Curl_easy *data, CURLcode result = CURLE_OK; (void)instate; - if(smtpcode/100 != 2) { + if(smtpcode / 100 != 2) { failf(data, "Got unexpected smtp-server response: %d", smtpcode); result = CURLE_WEIRD_SERVER_REPLY; } @@ -974,9 +966,9 @@ static CURLcode smtp_state_ehlo_resp(struct Curl_easy *data, (void)instate; - if(smtpcode/100 != 2 && smtpcode != 1) { - if(data->set.use_ssl <= CURLUSESSL_TRY - || Curl_conn_is_ssl(data->conn, FIRSTSOCKET)) + if(smtpcode / 100 != 2 && smtpcode != 1) { + if(data->set.use_ssl <= CURLUSESSL_TRY || + Curl_conn_is_ssl(data->conn, FIRSTSOCKET)) result = smtp_perform_helo(data, smtpc); else { failf(data, "Remote access denied: %d", smtpcode); @@ -1075,7 +1067,7 @@ static CURLcode smtp_state_helo_resp(struct Curl_easy *data, CURLcode result = CURLE_OK; (void)instate; - if(smtpcode/100 != 2) { + if(smtpcode / 100 != 2) { failf(data, "Remote access denied: %d", smtpcode); result = CURLE_REMOTE_ACCESS_DENIED; } @@ -1127,8 +1119,8 @@ static CURLcode smtp_state_command_resp(struct Curl_easy *data, (void)instate; - if((smtp->rcpt && smtpcode/100 != 2 && smtpcode != 553 && smtpcode != 1) || - (!smtp->rcpt && smtpcode/100 != 2 && smtpcode != 1)) { + if((smtp->rcpt && smtpcode / 100 != 2 && smtpcode != 553 && smtpcode != 1) || + (!smtp->rcpt && smtpcode / 100 != 2 && smtpcode != 1)) { failf(data, "Command failed: %d", smtpcode); result = CURLE_WEIRD_SERVER_REPLY; } @@ -1136,7 +1128,7 @@ static CURLcode smtp_state_command_resp(struct Curl_easy *data, if(!data->req.no_body) result = Curl_client_write(data, CLIENTWRITE_BODY, line, len); - if(smtpcode != 1) { + if(!result && (smtpcode != 1)) { if(smtp->rcpt) { smtp->rcpt = smtp->rcpt->next; @@ -1167,7 +1159,7 @@ static CURLcode smtp_state_mail_resp(struct Curl_easy *data, CURLcode result = CURLE_OK; (void)instate; - if(smtpcode/100 != 2) { + if(smtpcode / 100 != 2) { failf(data, "MAIL failed: %d", smtpcode); result = CURLE_SEND_ERROR; } @@ -1191,7 +1183,7 @@ static CURLcode smtp_state_rcpt_resp(struct Curl_easy *data, (void)instate; - is_smtp_err = (smtpcode/100 != 2); + is_smtp_err = (smtpcode / 100 != 2); /* If there is multiple RCPT TO to be issued, it is possible to ignore errors and proceed with only the valid addresses. */ @@ -1440,16 +1432,13 @@ static CURLcode smtp_connect(struct Curl_easy *data, bool *done) if(!smtpc) return CURLE_FAILED_INIT; - /* We always support persistent connections in SMTP */ - connkeep(data->conn, "SMTP default"); - PINGPONG_SETUP(&smtpc->pp, smtp_pp_statemachine, smtp_endofresp); /* Initialize the SASL storage */ Curl_sasl_init(&smtpc->sasl, data, &saslsmtp); /* Initialise the pingpong layer */ - Curl_pp_init(&smtpc->pp); + Curl_pp_init(&smtpc->pp, Curl_pgrs_now(data)); /* Parse the URL options */ result = smtp_parse_url_options(data->conn, smtpc); @@ -1697,10 +1686,7 @@ static CURLcode smtp_regular_transfer(struct Curl_easy *data, data->req.size = -1; /* Set the progress data */ - Curl_pgrsSetUploadCounter(data, 0); - Curl_pgrsSetDownloadCounter(data, 0); - Curl_pgrsSetUploadSize(data, -1); - Curl_pgrsSetDownloadSize(data, -1); + Curl_pgrsReset(data); /* Carry out the perform */ result = smtp_perform(data, smtpc, smtp, &connected, dophase_done); @@ -1714,13 +1700,12 @@ static CURLcode smtp_regular_transfer(struct Curl_easy *data, return result; } - static void smtp_easy_dtor(void *key, size_t klen, void *entry) { struct SMTP *smtp = entry; (void)key; (void)klen; - free(smtp); + curlx_free(smtp); } static void smtp_conn_dtor(void *key, size_t klen, void *entry) @@ -1730,7 +1715,7 @@ static void smtp_conn_dtor(void *key, size_t klen, void *entry) (void)klen; Curl_pp_disconnect(&smtpc->pp); Curl_safefree(smtpc->domain); - free(smtpc); + curlx_free(smtpc); } static CURLcode smtp_setup_connection(struct Curl_easy *data, @@ -1740,14 +1725,14 @@ static CURLcode smtp_setup_connection(struct Curl_easy *data, struct SMTP *smtp; CURLcode result = CURLE_OK; - smtpc = calloc(1, sizeof(*smtpc)); + smtpc = curlx_calloc(1, sizeof(*smtpc)); if(!smtpc || Curl_conn_meta_set(conn, CURL_META_SMTP_CONN, smtpc, smtp_conn_dtor)) { - result = CURLE_OUT_OF_MEMORY; - goto out; + result = CURLE_OUT_OF_MEMORY; + goto out; } - smtp = calloc(1, sizeof(*smtp)); + smtp = curlx_calloc(1, sizeof(*smtp)); if(!smtp || Curl_meta_set(data, CURL_META_SMTP_EASY, smtp, smtp_easy_dtor)) result = CURLE_OUT_OF_MEMORY; @@ -1881,7 +1866,7 @@ static CURLcode smtp_parse_address(const char *fqma, char **address, /* Duplicate the fully qualified email address so we can manipulate it, ensuring it does not contain the delimiters if specified */ - char *dup = strdup(fqma[0] == '<' ? fqma + 1 : fqma); + char *dup = curlx_strdup(fqma[0] == '<' ? fqma + 1 : fqma); if(!dup) return CURLE_OUT_OF_MEMORY; @@ -1927,6 +1912,7 @@ struct cr_eob_ctx { size_t eob; /* Number of bytes of the EOB (End Of Body) that have been received so far */ BIT(read_eos); /* we read an EOS from the next reader */ + BIT(processed_eos); /* we read and processed an EOS */ BIT(eos); /* we have returned an EOS */ }; @@ -1950,7 +1936,7 @@ static void cr_eob_close(struct Curl_easy *data, struct Curl_creader *reader) } /* this is the 5-bytes End-Of-Body marker for SMTP */ -#define SMTP_EOB "\r\n.\r\n" +#define SMTP_EOB "\r\n.\r\n" #define SMTP_EOB_FIND_LEN 3 /* client reader doing SMTP End-Of-Body escaping. */ @@ -1967,6 +1953,8 @@ static CURLcode cr_eob_read(struct Curl_easy *data, if(!ctx->read_eos && Curl_bufq_is_empty(&ctx->buf)) { /* Get more and convert it when needed */ result = Curl_creader_read(data, reader->next, buf, blen, &nread, &eos); + CURL_TRC_SMTP(data, "cr_eob_read, next_read(len=%zu) -> %d, %zu eos=%d", + blen, result, nread, eos); if(result) return result; @@ -2010,31 +1998,34 @@ static CURLcode cr_eob_read(struct Curl_easy *data, return result; } } + } - if(ctx->read_eos) { - /* if we last matched a CRLF or if the data was empty, add ".\r\n" - * to end the body. If we sent something and it did not end with "\r\n", - * add "\r\n.\r\n" to end the body */ - const char *eob = SMTP_EOB; - switch(ctx->n_eob) { - case 2: - /* seen a CRLF at the end, just add the remainder */ - eob = &SMTP_EOB[2]; - break; - case 3: - /* ended with '\r\n.', we should escape the last '.' */ - eob = "." SMTP_EOB; - break; - default: - break; - } - result = Curl_bufq_cwrite(&ctx->buf, eob, strlen(eob), &n); - if(result) - return result; + *peos = FALSE; + + if(ctx->read_eos && !ctx->processed_eos) { + /* if we last matched a CRLF or if the data was empty, add ".\r\n" + * to end the body. If we sent something and it did not end with "\r\n", + * add "\r\n.\r\n" to end the body */ + const char *eob = SMTP_EOB; + CURL_TRC_SMTP(data, "auto-ending mail body with '\\r\\n.\\r\\n'"); + switch(ctx->n_eob) { + case 2: + /* seen a CRLF at the end, just add the remainder */ + eob = &SMTP_EOB[2]; + break; + case 3: + /* ended with '\r\n.', we should escape the last '.' */ + eob = "." SMTP_EOB; + break; + default: + break; } + result = Curl_bufq_cwrite(&ctx->buf, eob, strlen(eob), &n); + if(result) + return result; + ctx->processed_eos = TRUE; } - *peos = FALSE; if(!Curl_bufq_is_empty(&ctx->buf)) { result = Curl_bufq_cread(&ctx->buf, buf, blen, pnread); } @@ -2043,6 +2034,7 @@ static CURLcode cr_eob_read(struct Curl_easy *data, if(ctx->read_eos && Curl_bufq_is_empty(&ctx->buf)) { /* no more data, read all, done. */ + CURL_TRC_SMTP(data, "mail body complete, returning EOS"); ctx->eos = TRUE; } *peos = ctx->eos; @@ -2079,8 +2071,7 @@ static CURLcode cr_eob_add(struct Curl_easy *data) struct Curl_creader *reader = NULL; CURLcode result; - result = Curl_creader_create(&reader, data, &cr_eob, - CURL_CR_CONTENT_ENCODE); + result = Curl_creader_create(&reader, data, &cr_eob, CURL_CR_CONTENT_ENCODE); if(!result) result = Curl_creader_add(data, reader); diff --git a/lib/socketpair.c b/lib/socketpair.c index 45e908bbf3a9..756fd7f181ea 100644 --- a/lib/socketpair.c +++ b/lib/socketpair.c @@ -23,9 +23,11 @@ ***************************************************************************/ #include "curl_setup.h" + #include "socketpair.h" #include "urldata.h" #include "rand.h" +#include "curlx/nonblock.h" #ifdef USE_EVENTFD @@ -107,37 +109,24 @@ int Curl_socketpair(int domain, int type, int protocol, } #endif /* USE_SOCKETPAIR */ #else /* !HAVE_SOCKETPAIR */ -#ifdef _WIN32 -/* - * This is a socketpair() implementation for Windows. - */ -#include -#ifdef HAVE_IO_H -#include -#endif -#else + #ifdef HAVE_NETDB_H #include #endif #ifdef HAVE_NETINET_IN_H -#include /* IPPROTO_TCP */ +#include /* for IPPROTO_TCP */ #endif #ifdef HAVE_ARPA_INET_H #include #endif + #ifndef INADDR_LOOPBACK #define INADDR_LOOPBACK 0x7f000001 -#endif /* !INADDR_LOOPBACK */ -#endif /* !_WIN32 */ +#endif -#include "curlx/nonblock.h" /* for curlx_nonblock */ #include "curlx/timeval.h" /* needed before select.h */ #include "select.h" /* for Curl_poll */ -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - int Curl_socketpair(int domain, int type, int protocol, curl_socket_t socks[2], bool nonblocking) { @@ -228,7 +217,7 @@ int Curl_socketpair(int domain, int type, int protocol, if(nread == -1) { int sockerr = SOCKERRNO; /* Do not block forever */ - if(curlx_timediff(curlx_now(), start) > (60 * 1000)) + if(curlx_timediff_ms(curlx_now(), start) > (60 * 1000)) goto error; if( #ifdef USE_WINSOCK diff --git a/lib/socketpair.h b/lib/socketpair.h index e601f5f71bee..a839a2c50d09 100644 --- a/lib/socketpair.h +++ b/lib/socketpair.h @@ -28,22 +28,20 @@ #ifdef USE_EVENTFD -#define wakeup_write write -#define wakeup_read read -#define wakeup_close close -#define wakeup_create(p,nb) Curl_eventfd(p,nb) +#define wakeup_write write +#define wakeup_read read +#define wakeup_close close +#define wakeup_create(p, nb) Curl_eventfd(p, nb) -#include int Curl_eventfd(curl_socket_t socks[2], bool nonblocking); #elif defined(HAVE_PIPE) -#define wakeup_write write -#define wakeup_read read -#define wakeup_close close -#define wakeup_create(p,nb) Curl_pipe(p,nb) +#define wakeup_write write +#define wakeup_read read +#define wakeup_close close +#define wakeup_create(p, nb) Curl_pipe(p, nb) -#include int Curl_pipe(curl_socket_t socks[2], bool nonblocking); #else /* !USE_EVENTFD && !HAVE_PIPE */ @@ -67,14 +65,12 @@ int Curl_pipe(curl_socket_t socks[2], bool nonblocking); #endif #define USE_SOCKETPAIR -#define wakeup_create(p,nb) \ +#define wakeup_create(p, nb) \ Curl_socketpair(SOCKETPAIR_FAMILY, SOCKETPAIR_TYPE, 0, p, nb) #endif /* USE_EVENTFD */ #ifndef CURL_DISABLE_SOCKETPAIR -#include - int Curl_socketpair(int domain, int type, int protocol, curl_socket_t socks[2], bool nonblocking); #endif diff --git a/lib/socks.c b/lib/socks.c index 10fca7b44c99..530621455718 100644 --- a/lib/socks.c +++ b/lib/socks.c @@ -35,20 +35,15 @@ #include "urldata.h" #include "bufq.h" -#include "sendf.h" +#include "curl_trc.h" #include "select.h" #include "cfilters.h" #include "connect.h" #include "curlx/timeval.h" #include "socks.h" -#include "multiif.h" /* for getsock macros */ #include "curlx/inet_pton.h" #include "url.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) #define DEBUG_AND_VERBOSE #endif @@ -137,7 +132,7 @@ CURLcode Curl_blockread_all(struct Curl_cfilter *cf, *pnread = 0; for(;;) { - timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE); + timediff_t timeout_ms = Curl_timeleft_ms(data, TRUE); if(timeout_ms < 0) { /* we already got the timeout */ return CURLE_OPERATION_TIMEDOUT; @@ -168,9 +163,9 @@ CURLcode Curl_blockread_all(struct Curl_cfilter *cf, #if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) #define DEBUG_AND_VERBOSE -#define sxstate(x,c,d,y) socksstate(x,c,d,y, __LINE__) +#define sxstate(x, c, d, y) socksstate(x, c, d, y, __LINE__) #else -#define sxstate(x,c,d,y) socksstate(x,c,d,y) +#define sxstate(x, c, d, y) socksstate(x, c, d, y) #endif /* always use this function to change state, to make debugging easier */ @@ -210,9 +205,9 @@ static CURLproxycode socks_failed(struct socks_state *sx, } static CURLproxycode socks_flush(struct socks_state *sx, - struct Curl_cfilter *cf, - struct Curl_easy *data, - bool *done) + struct Curl_cfilter *cf, + struct Curl_easy *data, + bool *done) { CURLcode result; size_t nwritten; @@ -308,7 +303,7 @@ static CURLproxycode socks4_req_add_user(struct socks_state *sx, return CURLPX_SEND_REQUEST; } else { - /* empty user name */ + /* empty username */ unsigned char b = 0; result = Curl_bufq_write(&sx->iobuf, &b, 1, &nwritten); if(result || (nwritten != 1)) @@ -331,12 +326,12 @@ static CURLproxycode socks4_resolving(struct socks_state *sx, if(sx->start_resolving) { /* need to resolve hostname to add destination address */ sx->start_resolving = FALSE; + DEBUGASSERT(sx->hostname && *sx->hostname); result = Curl_resolv(data, sx->hostname, sx->remote_port, cf->conn->ip_version, TRUE, &dns); if(result == CURLE_AGAIN) { - CURL_TRC_CF(data, cf, "SOCKS4 non-blocking resolve of %s", - sx->hostname); + CURL_TRC_CF(data, cf, "SOCKS4 non-blocking resolve of %s", sx->hostname); return CURLPX_OK; } else if(result) @@ -350,8 +345,7 @@ static CURLproxycode socks4_resolving(struct socks_state *sx, } if(result || !dns) { - failf(data, "Failed to resolve \"%s\" for SOCKS4 connect.", - sx->hostname); + failf(data, "Failed to resolve \"%s\" for SOCKS4 connect.", sx->hostname); return CURLPX_RESOLVE_HOST; } @@ -468,16 +462,16 @@ static CURLproxycode socks4_check_resp(struct socks_state *sx, } /* -* This function logs in to a SOCKS4 proxy and sends the specifics to the final -* destination server. -* -* Reference : -* https://www.openssh.com/txt/socks4.protocol -* -* Note : -* Set protocol4a=true for "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)" -* Nonsupport "Identification Protocol (RFC1413)" -*/ + * This function logs in to a SOCKS4 proxy and sends the specifics to the final + * destination server. + * + * Reference : + * https://www.openssh.com/txt/socks4.protocol + * + * Note : + * Set protocol4a=true for "SOCKS 4A (Simple Extension to SOCKS 4 Protocol)" + * Nonsupport "Identification Protocol (RFC1413)" + */ static CURLproxycode socks4_connect(struct Curl_cfilter *cf, struct socks_state *sx, struct Curl_easy *data) @@ -527,7 +521,7 @@ static CURLproxycode socks4_connect(struct Curl_cfilter *cf, /* socks4a, not resolving locally, sends the hostname. * add an invalid address + user + hostname */ unsigned char buf[4] = { 0, 0, 0, 1 }; - size_t hlen = strlen(sx->hostname) + 1; /* including NUL */ + size_t hlen = strlen(sx->hostname) + 1; /* including NUL */ if(hlen > 255) { failf(data, "SOCKS4: too long hostname"); @@ -736,7 +730,7 @@ static CURLproxycode socks5_auth_init(struct Curl_cfilter *cf, if(result || (nwritten != ulen)) return CURLPX_SEND_REQUEST; } - buf[0] = (unsigned char) plen; + buf[0] = (unsigned char)plen; result = Curl_bufq_write(&sx->iobuf, buf, 1, &nwritten); if(result || (nwritten != 1)) return CURLPX_SEND_REQUEST; @@ -765,13 +759,12 @@ static CURLproxycode socks5_check_auth_resp(struct socks_state *sx, /* ignore the first (VER) byte */ auth_status = resp[1]; - Curl_bufq_skip(&sx->iobuf, 2); - if(auth_status) { failf(data, "User was rejected by the SOCKS5 server (%d %d).", resp[0], resp[1]); return CURLPX_USER_REJECTED; } + Curl_bufq_skip(&sx->iobuf, 2); return CURLPX_OK; } @@ -817,7 +810,7 @@ static CURLproxycode socks5_req1_init(struct socks_state *sx, const size_t hostname_len = strlen(sx->hostname); desttype = 3; destination = (const unsigned char *)sx->hostname; - destlen = (unsigned char) hostname_len; /* one byte length */ + destlen = (unsigned char)hostname_len; /* one byte length */ } req[3] = desttype; @@ -859,12 +852,12 @@ static CURLproxycode socks5_resolving(struct socks_state *sx, if(sx->start_resolving) { /* need to resolve hostname to add destination address */ sx->start_resolving = FALSE; + DEBUGASSERT(sx->hostname && *sx->hostname); result = Curl_resolv(data, sx->hostname, sx->remote_port, cf->conn->ip_version, TRUE, &dns); if(result == CURLE_AGAIN) { - CURL_TRC_CF(data, cf, "SOCKS5 non-blocking resolve of %s", - sx->hostname); + CURL_TRC_CF(data, cf, "SOCKS5 non-blocking resolve of %s", sx->hostname); return CURLPX_OK; } else if(result) @@ -878,8 +871,7 @@ static CURLproxycode socks5_resolving(struct socks_state *sx, } if(result || !dns) { - failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.", - sx->hostname); + failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.", sx->hostname); presult = CURLPX_RESOLVE_HOST; goto out; } @@ -896,8 +888,7 @@ static CURLproxycode socks5_resolving(struct socks_state *sx, } #endif if(!hp) { - failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.", - sx->hostname); + failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.", sx->hostname); presult = CURLPX_RESOLVE_HOST; goto out; } @@ -1214,7 +1205,7 @@ static void socks_proxy_cf_free(struct Curl_cfilter *cf) struct socks_state *sxstate = cf->ctx; if(sxstate) { Curl_bufq_free(&sxstate->iobuf); - free(sxstate); + curlx_free(sxstate); cf->ctx = NULL; } } @@ -1246,9 +1237,11 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf, return result; if(!sx) { - cf->ctx = sx = calloc(1, sizeof(*sx)); - if(!sx) - return CURLE_OUT_OF_MEMORY; + cf->ctx = sx = curlx_calloc(1, sizeof(*sx)); + if(!sx) { + result = CURLE_OUT_OF_MEMORY; + goto out; + } /* for the secondary socket (FTP), use the "connect to host" * but ignore the "connect to port" (use the secondary port) @@ -1395,7 +1388,7 @@ static CURLcode socks_cf_query(struct Curl_cfilter *cf, struct Curl_cftype Curl_cft_socks_proxy = { "SOCKS", - CF_TYPE_IP_CONNECT|CF_TYPE_PROXY, + CF_TYPE_IP_CONNECT | CF_TYPE_PROXY, 0, socks_proxy_cf_destroy, socks_proxy_cf_connect, diff --git a/lib/socks.h b/lib/socks.h index f76bddc5f4e1..7c43e92e7e12 100644 --- a/lib/socks.h +++ b/lib/socks.h @@ -26,11 +26,7 @@ #include "curl_setup.h" -#ifdef CURL_DISABLE_PROXY -#define Curl_SOCKS4(a,b,c,d,e) CURLE_NOT_BUILT_IN -#define Curl_SOCKS5(a,b,c,d,e,f) CURLE_NOT_BUILT_IN -#define Curl_SOCKS_getsock(x,y,z) 0 -#else +#ifndef CURL_DISABLE_PROXY /* * Helper read-from-socket functions. Does the same as Curl_read() but it * blocks until all bytes amount of buffersize will be read. No more, no less. @@ -56,6 +52,6 @@ CURLcode Curl_cf_socks_proxy_insert_after(struct Curl_cfilter *cf_at, extern struct Curl_cftype Curl_cft_socks_proxy; -#endif /* CURL_DISABLE_PROXY */ +#endif /* !CURL_DISABLE_PROXY */ #endif /* HEADER_CURL_SOCKS_H */ diff --git a/lib/socks_gssapi.c b/lib/socks_gssapi.c index 5ad93441a830..ce493c03931c 100644 --- a/lib/socks_gssapi.c +++ b/lib/socks_gssapi.c @@ -29,18 +29,14 @@ #include "curl_gssapi.h" #include "urldata.h" -#include "sendf.h" +#include "curl_trc.h" #include "cfilters.h" #include "connect.h" +#include "curlx/nonblock.h" #include "curlx/timeval.h" #include "socks.h" -#include "curlx/warnless.h" #include "strdup.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - #if defined(__GNUC__) && defined(__APPLE__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" @@ -71,8 +67,7 @@ static int check_gss_err(struct Curl_easy *data, GSS_C_NULL_OID, &msg_ctx, &status_string); if(maj_stat == GSS_S_COMPLETE) { - if(curlx_dyn_addn(&dbuf, status_string.value, - status_string.length)) + if(curlx_dyn_addn(&dbuf, status_string.value, status_string.length)) return 1; /* error */ gss_release_buffer(&min_stat, &status_string); break; @@ -89,8 +84,7 @@ static int check_gss_err(struct Curl_easy *data, GSS_C_NULL_OID, &msg_ctx, &status_string); if(maj_stat == GSS_S_COMPLETE) { - if(curlx_dyn_addn(&dbuf, status_string.value, - status_string.length)) + if(curlx_dyn_addn(&dbuf, status_string.value, status_string.length)) return 1; /* error */ gss_release_buffer(&min_stat, &status_string); break; @@ -126,14 +120,12 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, gss_name_t server = GSS_C_NO_NAME; gss_name_t gss_client_name = GSS_C_NO_NAME; unsigned short us_length; - char *user = NULL; unsigned char socksreq[4]; /* room for GSS-API exchange header only */ const char *serviceptr = data->set.str[STRING_PROXY_SERVICE_NAME] ? data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd"; const size_t serviceptr_length = strlen(serviceptr); gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT; - /* GSS-API request looks like * +----+------+-----+----------------+ * |VER | MTYP | LEN | TOKEN | @@ -150,11 +142,11 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, return CURLE_OUT_OF_MEMORY; gss_major_status = gss_import_name(&gss_minor_status, &service, - (gss_OID) GSS_C_NULL_OID, &server); + (gss_OID)GSS_C_NULL_OID, &server); } else { - service.value = malloc(serviceptr_length + - strlen(conn->socks_proxy.host.name) + 2); + service.value = curlx_malloc(serviceptr_length + + strlen(conn->socks_proxy.host.name) + 2); if(!service.value) return CURLE_OUT_OF_MEMORY; service.length = serviceptr_length + @@ -166,7 +158,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, GSS_C_NT_HOSTBASED_SERVICE, &server); } - gss_release_buffer(&gss_status, &service); /* clear allocated memory */ + Curl_safefree(service.value); + service.length = 0; if(check_gss_err(data, gss_major_status, gss_minor_status, "gss_import_name()")) { @@ -191,8 +184,10 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, TRUE, &gss_ret_flags); - if(gss_token != GSS_C_NO_BUFFER) - gss_release_buffer(&gss_status, &gss_recv_token); + if(gss_token != GSS_C_NO_BUFFER) { + Curl_safefree(gss_recv_token.value); + gss_recv_token.length = 0; + } if(check_gss_err(data, gss_major_status, gss_minor_status, "gss_init_sec_context") || /* the size needs to fit in a 16 bit field */ @@ -210,8 +205,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, us_length = htons((unsigned short)gss_send_token.length); memcpy(socksreq + 2, &us_length, sizeof(short)); - code = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, - FALSE, &nwritten); + code = Curl_conn_cf_send(cf->next, data, socksreq, 4, FALSE, &nwritten); if(code || (nwritten != 4)) { failf(data, "Failed to send GSS-API authentication request."); gss_release_name(&gss_status, &server); @@ -221,7 +215,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, } code = Curl_conn_cf_send(cf->next, data, - (char *)gss_send_token.value, + gss_send_token.value, gss_send_token.length, FALSE, &nwritten); if(code || (gss_send_token.length != nwritten)) { failf(data, "Failed to send GSS-API authentication token."); @@ -230,7 +224,6 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, Curl_gss_delete_sec_context(&gss_status, &gss_context, NULL); return CURLE_COULDNT_CONNECT; } - } gss_release_buffer(&gss_status, &gss_send_token); @@ -276,7 +269,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, us_length = ntohs(us_length); gss_recv_token.length = us_length; - gss_recv_token.value = malloc(us_length); + gss_recv_token.value = curlx_malloc(gss_recv_token.length); if(!gss_recv_token.value) { failf(data, "Could not allocate memory for GSS-API authentication " @@ -292,7 +285,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, if(result || (actualread != us_length)) { failf(data, "Failed to receive GSS-API authentication token."); gss_release_name(&gss_status, &server); - gss_release_buffer(&gss_status, &gss_recv_token); + Curl_safefree(gss_recv_token.value); + gss_recv_token.length = 0; Curl_gss_delete_sec_context(&gss_status, &gss_context, NULL); return CURLE_COULDNT_CONNECT; } @@ -323,21 +317,12 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, failf(data, "Failed to determine username."); return CURLE_COULDNT_CONNECT; } - user = malloc(gss_send_token.length + 1); - if(!user) { - Curl_gss_delete_sec_context(&gss_status, &gss_context, NULL); - gss_release_name(&gss_status, &gss_client_name); - gss_release_buffer(&gss_status, &gss_send_token); - return CURLE_OUT_OF_MEMORY; - } - memcpy(user, gss_send_token.value, gss_send_token.length); - user[gss_send_token.length] = '\0'; + infof(data, "SOCKS5 server authenticated user %.*s with GSS-API.", + (int)gss_send_token.length, (char *)gss_send_token.value); + gss_release_name(&gss_status, &gss_client_name); gss_release_buffer(&gss_status, &gss_send_token); - infof(data, "SOCKS5 server authenticated user %s with GSS-API.",user); - free(user); - user = NULL; /* Do encryption */ socksreq[0] = 1; /* GSS-API subnegotiation version */ @@ -391,7 +376,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, } else { gss_send_token.length = 1; - gss_send_token.value = Curl_memdup(&gss_enc, 1); + gss_send_token.value = Curl_memdup(&gss_enc, gss_send_token.length); if(!gss_send_token.value) { Curl_gss_delete_sec_context(&gss_status, &gss_context, NULL); return CURLE_OUT_OF_MEMORY; @@ -402,20 +387,21 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, &gss_conf_state, &gss_w_token); if(check_gss_err(data, gss_major_status, gss_minor_status, "gss_wrap")) { - gss_release_buffer(&gss_status, &gss_send_token); + Curl_safefree(gss_send_token.value); + gss_send_token.length = 0; gss_release_buffer(&gss_status, &gss_w_token); Curl_gss_delete_sec_context(&gss_status, &gss_context, NULL); failf(data, "Failed to wrap GSS-API encryption value into token."); return CURLE_COULDNT_CONNECT; } - gss_release_buffer(&gss_status, &gss_send_token); + Curl_safefree(gss_send_token.value); + gss_send_token.length = 0; us_length = htons((unsigned short)gss_w_token.length); memcpy(socksreq + 2, &us_length, sizeof(short)); } - code = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, FALSE, - &nwritten); + code = Curl_conn_cf_send(cf->next, data, socksreq, 4, FALSE, &nwritten); if(code || (nwritten != 4)) { failf(data, "Failed to send GSS-API encryption request."); gss_release_buffer(&gss_status, &gss_w_token); @@ -425,8 +411,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, if(data->set.socks5_gssapi_nec) { memcpy(socksreq, &gss_enc, 1); - code = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 1, FALSE, - &nwritten); + code = Curl_conn_cf_send(cf->next, data, socksreq, 1, FALSE, &nwritten); if(code || (nwritten != 1)) { failf(data, "Failed to send GSS-API encryption type."); Curl_gss_delete_sec_context(&gss_status, &gss_context, NULL); @@ -434,7 +419,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, } } else { - code = Curl_conn_cf_send(cf->next, data, (char *)gss_w_token.value, + code = Curl_conn_cf_send(cf->next, data, gss_w_token.value, gss_w_token.length, FALSE, &nwritten); if(code || (gss_w_token.length != nwritten)) { failf(data, "Failed to send GSS-API encryption type."); @@ -471,7 +456,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, us_length = ntohs(us_length); gss_recv_token.length = us_length; - gss_recv_token.value = malloc(gss_recv_token.length); + gss_recv_token.value = curlx_malloc(gss_recv_token.length); if(!gss_recv_token.value) { Curl_gss_delete_sec_context(&gss_status, &gss_context, NULL); return CURLE_OUT_OF_MEMORY; @@ -481,7 +466,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, if(result || (actualread != us_length)) { failf(data, "Failed to receive GSS-API encryption type."); - gss_release_buffer(&gss_status, &gss_recv_token); + Curl_safefree(gss_recv_token.value); + gss_recv_token.length = 0; Curl_gss_delete_sec_context(&gss_status, &gss_context, NULL); return CURLE_COULDNT_CONNECT; } @@ -492,13 +478,15 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, 0, GSS_C_QOP_DEFAULT); if(check_gss_err(data, gss_major_status, gss_minor_status, "gss_unwrap")) { - gss_release_buffer(&gss_status, &gss_recv_token); + Curl_safefree(gss_recv_token.value); + gss_recv_token.length = 0; gss_release_buffer(&gss_status, &gss_w_token); Curl_gss_delete_sec_context(&gss_status, &gss_context, NULL); failf(data, "Failed to unwrap GSS-API encryption value into token."); return CURLE_COULDNT_CONNECT; } - gss_release_buffer(&gss_status, &gss_recv_token); + Curl_safefree(gss_recv_token.value); + gss_recv_token.length = 0; if(gss_w_token.length != 1) { failf(data, "Invalid GSS-API encryption response length (%zu).", @@ -515,13 +503,15 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, if(gss_recv_token.length != 1) { failf(data, "Invalid GSS-API encryption response length (%zu).", gss_recv_token.length); - gss_release_buffer(&gss_status, &gss_recv_token); + Curl_safefree(gss_recv_token.value); + gss_recv_token.length = 0; Curl_gss_delete_sec_context(&gss_status, &gss_context, NULL); return CURLE_COULDNT_CONNECT; } memcpy(socksreq, gss_recv_token.value, gss_recv_token.length); - gss_release_buffer(&gss_status, &gss_recv_token); + Curl_safefree(gss_recv_token.value); + gss_recv_token.length = 0; } (void)curlx_nonblock(sock, TRUE); diff --git a/lib/socks_sspi.c b/lib/socks_sspi.c index 54049e8c9928..4a206a06ad07 100644 --- a/lib/socks_sspi.c +++ b/lib/socks_sspi.c @@ -28,20 +28,15 @@ #if defined(USE_WINDOWS_SSPI) && !defined(CURL_DISABLE_PROXY) #include "urldata.h" -#include "sendf.h" +#include "curl_trc.h" #include "cfilters.h" #include "connect.h" #include "strerror.h" +#include "curlx/nonblock.h" #include "curlx/timeval.h" #include "socks.h" #include "curl_sspi.h" #include "curlx/multibyte.h" -#include "curlx/warnless.h" -#include "strdup.h" - -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" /* * Helper sspi error functions. @@ -88,8 +83,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, unsigned long qop; unsigned char socksreq[4]; /* room for GSS-API exchange header only */ const char *service = data->set.str[STRING_PROXY_SERVICE_NAME] ? - data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd"; - char *etbuf; + data->set.str[STRING_PROXY_SERVICE_NAME] : "rcmd"; + uint8_t *etbuf; size_t etbuf_size; /* GSS-API request looks like @@ -102,7 +97,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, /* prepare service name */ if(strchr(service, '/')) - service_name = strdup(service); + service_name = curlx_strdup(service); else service_name = curl_maprintf("%s/%s", service, conn->socks_proxy.host.name); @@ -157,7 +152,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, (void)curlx_nonblock(sock, FALSE); /* As long as we need to keep sending some context info, and there is no */ - /* errors, keep sending it... */ + /* errors, keep sending it... */ for(;;) { TCHAR *sname; @@ -180,7 +175,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, &output_desc, &sspi_ret_flags, NULL); - curlx_unicodefree(sname); + curlx_free(sname); Curl_safefree(sspi_recv_token.pvBuffer); sspi_recv_token.cbBuffer = 0; @@ -192,8 +187,8 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, } if(sspi_send_token.cbBuffer) { - socksreq[0] = 1; /* GSS-API subnegotiation version */ - socksreq[1] = 1; /* authentication message type */ + socksreq[0] = 1; /* GSS-API subnegotiation version */ + socksreq[1] = 1; /* authentication message type */ if(sspi_send_token.cbBuffer > 0xffff) { /* needs to fit in an unsigned 16 bit field */ result = CURLE_COULDNT_CONNECT; @@ -202,8 +197,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, us_length = htons((unsigned short)sspi_send_token.cbBuffer); memcpy(socksreq + 2, &us_length, sizeof(short)); - code = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, FALSE, - &written); + code = Curl_conn_cf_send(cf->next, data, socksreq, 4, FALSE, &written); if(code || (written != 4)) { failf(data, "Failed to send SSPI authentication request."); result = CURLE_COULDNT_CONNECT; @@ -211,7 +205,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, } code = Curl_conn_cf_send(cf->next, data, - (char *)sspi_send_token.pvBuffer, + sspi_send_token.pvBuffer, sspi_send_token.cbBuffer, FALSE, &written); if(code || (sspi_send_token.cbBuffer != written)) { failf(data, "Failed to send SSPI authentication token."); @@ -269,7 +263,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, us_length = ntohs(us_length); sspi_recv_token.cbBuffer = us_length; - sspi_recv_token.pvBuffer = malloc(us_length); + sspi_recv_token.pvBuffer = curlx_malloc(us_length); if(!sspi_recv_token.pvBuffer) { result = CURLE_OUT_OF_MEMORY; @@ -304,15 +298,15 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, 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); + curlx_free(user_utf8); #endif Curl_pSecFn->FreeContextBuffer(names.sUserName); names.sUserName = NULL; } /* Do encryption */ - socksreq[0] = 1; /* GSS-API subnegotiation version */ - socksreq[1] = 2; /* encryption message type */ + socksreq[0] = 1; /* GSS-API subnegotiation version */ + socksreq[1] = 2; /* encryption message type */ gss_enc = 0; /* no data protection */ /* do confidentiality protection if supported */ @@ -324,7 +318,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, infof(data, "SOCKS5 server supports GSS-API %s data protection.", (gss_enc == 0) ? "no" : - ((gss_enc == 1) ? "integrity":"confidentiality") ); + ((gss_enc == 1) ? "integrity" : "confidentiality") ); /* * Sending the encryption type in clear seems wrong. It should be @@ -373,7 +367,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, sspi_w_token[0].cbBuffer = sspi_sizes.cbSecurityTrailer; sspi_w_token[0].BufferType = SECBUFFER_TOKEN; - sspi_w_token[0].pvBuffer = malloc(sspi_sizes.cbSecurityTrailer); + sspi_w_token[0].pvBuffer = curlx_malloc(sspi_sizes.cbSecurityTrailer); if(!sspi_w_token[0].pvBuffer) { result = CURLE_OUT_OF_MEMORY; @@ -381,7 +375,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, } sspi_w_token[1].cbBuffer = 1; - sspi_w_token[1].pvBuffer = malloc(1); + sspi_w_token[1].pvBuffer = curlx_malloc(1); if(!sspi_w_token[1].pvBuffer) { result = CURLE_OUT_OF_MEMORY; goto error; @@ -390,7 +384,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, memcpy(sspi_w_token[1].pvBuffer, &gss_enc, 1); sspi_w_token[2].BufferType = SECBUFFER_PADDING; sspi_w_token[2].cbBuffer = sspi_sizes.cbBlockSize; - sspi_w_token[2].pvBuffer = malloc(sspi_sizes.cbBlockSize); + sspi_w_token[2].pvBuffer = curlx_malloc(sspi_sizes.cbBlockSize); if(!sspi_w_token[2].pvBuffer) { result = CURLE_OUT_OF_MEMORY; goto error; @@ -405,13 +399,13 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, } etbuf_size = sspi_w_token[0].cbBuffer + sspi_w_token[1].cbBuffer + - sspi_w_token[2].cbBuffer; + sspi_w_token[2].cbBuffer; if(etbuf_size > 0xffff) { /* needs to fit in an unsigned 16 bit field */ result = CURLE_COULDNT_CONNECT; goto error; } - etbuf = malloc(etbuf_size); + etbuf = curlx_malloc(etbuf_size); if(!etbuf) { result = CURLE_OUT_OF_MEMORY; goto error; @@ -434,8 +428,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, memcpy(socksreq + 2, &us_length, sizeof(short)); } - code = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 4, FALSE, - &written); + code = Curl_conn_cf_send(cf->next, data, socksreq, 4, FALSE, &written); if(code || (written != 4)) { failf(data, "Failed to send SSPI encryption request."); result = CURLE_COULDNT_CONNECT; @@ -444,8 +437,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, if(data->set.socks5_gssapi_nec) { memcpy(socksreq, &gss_enc, 1); - code = Curl_conn_cf_send(cf->next, data, (char *)socksreq, 1, FALSE, - &written); + code = Curl_conn_cf_send(cf->next, data, socksreq, 1, FALSE, &written); if(code || (written != 1)) { failf(data, "Failed to send SSPI encryption type."); result = CURLE_COULDNT_CONNECT; @@ -490,7 +482,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, us_length = ntohs(us_length); sspi_w_token[0].cbBuffer = us_length; - sspi_w_token[0].pvBuffer = malloc(us_length); + sspi_w_token[0].pvBuffer = curlx_malloc(us_length); if(!sspi_w_token[0].pvBuffer) { result = CURLE_OUT_OF_MEMORY; goto error; @@ -506,7 +498,6 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, goto error; } - if(!data->set.socks5_gssapi_nec) { wrap_desc.cBuffers = 2; sspi_w_token[0].BufferType = SECBUFFER_STREAM; @@ -519,7 +510,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, /* since sspi_w_token[1].pvBuffer is allocated by the SSPI in this case, it must be freed in this block using FreeContextBuffer() instead of - potentially in error cleanup using free(). */ + potentially in error cleanup using curlx_free(). */ if(check_sspi_err(data, status, "DecryptMessage")) { failf(data, "Failed to query security context attributes."); @@ -562,7 +553,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, } (void)curlx_nonblock(sock, TRUE); - infof(data, "SOCKS5 access with%s protection granted.", + infof(data, "SOCKS5 access with%s protection granted BUT NOT USED.", (socksreq[0] == 0) ? "out GSS-API data": ((socksreq[0] == 1) ? " GSS-API integrity" : " GSS-API confidentiality")); @@ -582,18 +573,18 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, return CURLE_OK; error: (void)curlx_nonblock(sock, TRUE); - free(service_name); + curlx_free(service_name); Curl_pSecFn->DeleteSecurityContext(&sspi_context); Curl_pSecFn->FreeCredentialsHandle(&cred_handle); - free(sspi_recv_token.pvBuffer); + curlx_free(sspi_recv_token.pvBuffer); if(sspi_send_token.pvBuffer) Curl_pSecFn->FreeContextBuffer(sspi_send_token.pvBuffer); if(names.sUserName) Curl_pSecFn->FreeContextBuffer(names.sUserName); - free(sspi_w_token[0].pvBuffer); - free(sspi_w_token[1].pvBuffer); - free(sspi_w_token[2].pvBuffer); - free(etbuf); + curlx_free(sspi_w_token[0].pvBuffer); + curlx_free(sspi_w_token[1].pvBuffer); + curlx_free(sspi_w_token[2].pvBuffer); + curlx_free(etbuf); return result; } #endif diff --git a/lib/speedcheck.c b/lib/speedcheck.c deleted file mode 100644 index b063e5d4f208..000000000000 --- a/lib/speedcheck.c +++ /dev/null @@ -1,80 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) Daniel Stenberg, , et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at https://curl.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the 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 -#include "urldata.h" -#include "sendf.h" -#include "transfer.h" -#include "multiif.h" -#include "speedcheck.h" - -void Curl_speedinit(struct Curl_easy *data) -{ - memset(&data->state.keeps_speed, 0, sizeof(struct curltime)); -} - -/* - * @unittest: 1606 - */ -CURLcode Curl_speedcheck(struct Curl_easy *data, - struct curltime now) -{ - if(Curl_xfer_recv_is_paused(data)) - /* A paused transfer is not qualified for speed checks */ - return CURLE_OK; - - if((data->progress.current_speed >= 0) && data->set.low_speed_time) { - if(data->progress.current_speed < data->set.low_speed_limit) { - if(!data->state.keeps_speed.tv_sec) - /* under the limit at this very moment */ - data->state.keeps_speed = now; - else { - /* how long has it been under the limit */ - timediff_t howlong = curlx_timediff(now, data->state.keeps_speed); - - if(howlong >= data->set.low_speed_time * 1000) { - /* too long */ - failf(data, - "Operation too slow. " - "Less than %ld bytes/sec transferred the last %ld seconds", - data->set.low_speed_limit, - data->set.low_speed_time); - return CURLE_OPERATION_TIMEDOUT; - } - } - } - else - /* faster right now */ - data->state.keeps_speed.tv_sec = 0; - } - - if(data->set.low_speed_limit) - /* if low speed limit is enabled, set the expire timer to make this - connection's speed get checked again in a second */ - Curl_expire(data, 1000, EXPIRE_SPEEDCHECK); - - return CURLE_OK; -} diff --git a/lib/splay.c b/lib/splay.c index 3ca8678b2b2f..a95eb10d8502 100644 --- a/lib/splay.c +++ b/lib/splay.c @@ -34,13 +34,13 @@ * zero : when i is equal to j * positive when : when i is larger than j */ -#define compare(i,j) curlx_timediff_us(i,j) +#define splay_compare(i, j) curlx_ptimediff_us(i, j) /* * Splay using the key i (which may or may not be in the tree.) The starting * root is t. */ -struct Curl_tree *Curl_splay(struct curltime i, +struct Curl_tree *Curl_splay(const struct curltime *pkey, struct Curl_tree *t) { struct Curl_tree N, *l, *r, *y; @@ -51,11 +51,11 @@ struct Curl_tree *Curl_splay(struct curltime i, l = r = &N; for(;;) { - timediff_t comp = compare(i, t->key); + timediff_t comp = splay_compare(pkey, &t->key); if(comp < 0) { if(!t->smaller) break; - if(compare(i, t->smaller->key) < 0) { + if(splay_compare(pkey, &t->smaller->key) < 0) { y = t->smaller; /* rotate smaller */ t->smaller = y->larger; y->larger = t; @@ -70,7 +70,7 @@ struct Curl_tree *Curl_splay(struct curltime i, else if(comp > 0) { if(!t->larger) break; - if(compare(i, t->larger->key) > 0) { + if(splay_compare(pkey, &t->larger->key) > 0) { y = t->larger; /* rotate larger */ t->larger = y->smaller; y->smaller = t; @@ -103,16 +103,16 @@ static const struct curltime SPLAY_SUBNODE = { * * @unittest: 1309 */ -struct Curl_tree *Curl_splayinsert(struct curltime i, +struct Curl_tree *Curl_splayinsert(const struct curltime *pkey, struct Curl_tree *t, struct Curl_tree *node) { DEBUGASSERT(node); if(t) { - t = Curl_splay(i, t); + t = Curl_splay(pkey, t); DEBUGASSERT(t); - if(compare(i, t->key) == 0) { + if(splay_compare(pkey, &t->key) == 0) { /* There already exists a node in the tree with the same key. Build a doubly-linked circular list of nodes. We add the new 'node' struct to the end of this list. */ @@ -130,18 +130,17 @@ struct Curl_tree *Curl_splayinsert(struct curltime i, if(!t) { node->smaller = node->larger = NULL; } - else if(compare(i, t->key) < 0) { + else if(splay_compare(pkey, &t->key) < 0) { node->smaller = t->smaller; node->larger = t; t->smaller = NULL; - } else { node->larger = t->larger; node->smaller = t; t->larger = NULL; } - node->key = i; + node->key = *pkey; /* no identical nodes (yet), we are the only one in the list of nodes */ node->samen = node; @@ -152,11 +151,11 @@ struct Curl_tree *Curl_splayinsert(struct curltime i, /* Finds and deletes the best-fit node from the tree. Return a pointer to the resulting tree. best-fit means the smallest node if it is not larger than the key */ -struct Curl_tree *Curl_splaygetbest(struct curltime i, +struct Curl_tree *Curl_splaygetbest(const struct curltime *pkey, struct Curl_tree *t, struct Curl_tree **removed) { - static const struct curltime tv_zero = {0, 0}; + static const struct curltime tv_zero = { 0, 0 }; struct Curl_tree *x; if(!t) { @@ -165,9 +164,9 @@ struct Curl_tree *Curl_splaygetbest(struct curltime i, } /* find smallest */ - t = Curl_splay(tv_zero, t); + t = Curl_splay(&tv_zero, t); DEBUGASSERT(t); - if(compare(i, t->key) < 0) { + if(splay_compare(pkey, &t->key) < 0) { /* even the smallest is too big */ *removed = NULL; return t; @@ -197,7 +196,6 @@ struct Curl_tree *Curl_splaygetbest(struct curltime i, return x; } - /* Deletes the node we point out from the tree if it is there. Stores a * pointer to the new resulting tree in 'newroot'. * @@ -220,7 +218,7 @@ int Curl_splayremove(struct Curl_tree *t, DEBUGASSERT(removenode); - if(compare(SPLAY_SUBNODE, removenode->key) == 0) { + if(splay_compare(&SPLAY_SUBNODE, &removenode->key) == 0) { /* It is a subnode within a 'same' linked list and thus we can unlink it easily. */ DEBUGASSERT(removenode->samen != removenode); @@ -238,7 +236,7 @@ int Curl_splayremove(struct Curl_tree *t, return 0; } - t = Curl_splay(removenode->key, t); + t = Curl_splay(&removenode->key, t); DEBUGASSERT(t); /* First make sure that we got the same root node as the one we want @@ -270,7 +268,7 @@ int Curl_splayremove(struct Curl_tree *t, if(!t->smaller) x = t->larger; else { - x = Curl_splay(removenode->key, t->smaller); + x = Curl_splay(&removenode->key, t->smaller); DEBUGASSERT(x); x->larger = t->larger; } diff --git a/lib/splay.h b/lib/splay.h index ccc3781ec167..9ed96f63e4ea 100644 --- a/lib/splay.h +++ b/lib/splay.h @@ -24,6 +24,7 @@ * ***************************************************************************/ #include "curl_setup.h" + #include "curlx/timeval.h" /* only use function calls to access this struct */ @@ -36,14 +37,14 @@ struct Curl_tree { void *ptr; /* data the splay code does not care about */ }; -struct Curl_tree *Curl_splay(struct curltime i, +struct Curl_tree *Curl_splay(const struct curltime *pkey, struct Curl_tree *t); -struct Curl_tree *Curl_splayinsert(struct curltime key, +struct Curl_tree *Curl_splayinsert(const struct curltime *pkey, struct Curl_tree *t, struct Curl_tree *newnode); -struct Curl_tree *Curl_splaygetbest(struct curltime key, +struct Curl_tree *Curl_splaygetbest(const struct curltime *pkey, struct Curl_tree *t, struct Curl_tree **removed); diff --git a/lib/strcase.c b/lib/strcase.c index ee5b9072c4cc..f36d2b8f108f 100644 --- a/lib/strcase.c +++ b/lib/strcase.c @@ -24,62 +24,64 @@ #include "curl_setup.h" -#include - #include "strcase.h" /* Mapping table to go from lowercase to uppercase for plain ASCII.*/ static const unsigned char touppermap[256] = { -0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, -22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, -41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, -60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, -79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 65, -66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, -85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, -134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, -150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, -166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, -182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, -198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, -214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, -230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, -246, 247, 248, 249, 250, 251, 252, 253, 254, 255 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255 }; /* Mapping table to go from uppercase to lowercase for plain ASCII.*/ static const unsigned char tolowermap[256] = { -0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, -22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, -42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, -111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, -96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, -112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, -128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, -144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, -160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, -176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, -192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, -208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, -224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, -240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, + 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, + 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, + 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, + 255 }; - /* Portable, consistent toupper. Do not use toupper() because its behavior is altered by the current locale. */ char Curl_raw_toupper(char in) { - return (char)touppermap[(unsigned char) in]; + return (char)touppermap[(unsigned char)in]; } - /* Portable, consistent tolower. Do not use tolower() because its behavior is altered by the current locale. */ char Curl_raw_tolower(char in) { - return (char)tolowermap[(unsigned char) in]; + return (char)tolowermap[(unsigned char)in]; } /* Copy an upper case version of the string from src to dest. The @@ -133,7 +135,7 @@ int Curl_timestrcmp(const char *a, const char *b) if(a && b) { while(1) { - match |= a[i]^b[i]; + match |= a[i] ^ b[i]; if(!a[i] || !b[i]) break; i++; diff --git a/lib/strcase.h b/lib/strcase.h index 915c996926d0..060ebba6e5a6 100644 --- a/lib/strcase.h +++ b/lib/strcase.h @@ -24,14 +24,14 @@ * ***************************************************************************/ -#include +#include "curl_setup.h" char Curl_raw_toupper(char in); char Curl_raw_tolower(char in); /* checkprefix() is a shorter version of the above, used when the first argument is the string literal */ -#define checkprefix(a,b) curl_strnequal(b, STRCONST(a)) +#define checkprefix(a, b) curl_strnequal(b, STRCONST(a)) void Curl_strntoupper(char *dest, const char *src, size_t n); void Curl_strntolower(char *dest, const char *src, size_t n); diff --git a/lib/strdup.c b/lib/strdup.c index 3339e909ee79..99976a5deaed 100644 --- a/lib/strdup.c +++ b/lib/strdup.c @@ -24,17 +24,11 @@ #include "curl_setup.h" -#include - #ifdef _WIN32 #include #endif #include "strdup.h" -#include "curl_memory.h" - -/* The last #include file should be: */ -#include "memdebug.h" #ifndef HAVE_STRDUP char *Curl_strdup(const char *str) @@ -47,7 +41,7 @@ char *Curl_strdup(const char *str) len = strlen(str) + 1; - newstr = malloc(len); + newstr = curlx_malloc(len); if(!newstr) return (char *)NULL; @@ -90,7 +84,7 @@ wchar_t *Curl_wcsdup(const wchar_t *src) ***************************************************************************/ void *Curl_memdup(const void *src, size_t length) { - void *buffer = malloc(length); + void *buffer = curlx_malloc(length); if(!buffer) return NULL; /* fail */ @@ -111,7 +105,7 @@ void *Curl_memdup(const void *src, size_t length) ***************************************************************************/ void *Curl_memdup0(const char *src, size_t length) { - char *buf = (length < SIZE_MAX) ? malloc(length + 1) : NULL; + char *buf = (length < SIZE_MAX) ? curlx_malloc(length + 1) : NULL; if(!buf) return NULL; if(length) { @@ -126,7 +120,7 @@ void *Curl_memdup0(const char *src, size_t length) * * Curl_saferealloc(ptr, size) * - * Does a normal realloc(), but will free the data pointer if the realloc + * Does a normal curlx_realloc(), but will free the data pointer if the realloc * fails. If 'size' is non-zero, it will free the data and return a failure. * * This convenience function is provided and used to help us avoid a common @@ -138,9 +132,9 @@ void *Curl_memdup0(const char *src, size_t length) ***************************************************************************/ void *Curl_saferealloc(void *ptr, size_t size) { - void *datap = realloc(ptr, size); + void *datap = curlx_realloc(ptr, size); if(size && !datap) /* only free 'ptr' if size was non-zero */ - free(ptr); + curlx_free(ptr); return datap; } diff --git a/lib/strdup.h b/lib/strdup.h index 238a2611f645..cd01ffbdb894 100644 --- a/lib/strdup.h +++ b/lib/strdup.h @@ -29,10 +29,9 @@ char *Curl_strdup(const char *str); #endif #ifdef _WIN32 -wchar_t* Curl_wcsdup(const wchar_t* src); +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/strequal.c b/lib/strequal.c index 17dd34b7f3af..14edad7e8c28 100644 --- a/lib/strequal.c +++ b/lib/strequal.c @@ -24,7 +24,6 @@ #include "curl_setup.h" -#include #include "strcase.h" /* diff --git a/lib/strerror.c b/lib/strerror.c index 5b82d7f96556..6c655f4fe65e 100644 --- a/lib/strerror.c +++ b/lib/strerror.c @@ -24,22 +24,15 @@ #include "curl_setup.h" -#include -#include - #ifdef USE_WINDOWS_SSPI #include "curl_sspi.h" #endif #include "curlx/winapi.h" #include "strerror.h" +#include "curlx/strcopy.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - -const char * -curl_easy_strerror(CURLcode error) +const char *curl_easy_strerror(CURLcode error) { #ifndef CURL_DISABLE_VERBOSE_STRINGS switch(error) { @@ -57,7 +50,7 @@ curl_easy_strerror(CURLcode error) case CURLE_NOT_BUILT_IN: return "A requested feature, protocol or option was not found built-in in" - " this libcurl due to a build-time decision."; + " this libcurl due to a build-time decision."; case CURLE_COULDNT_RESOLVE_PROXY: return "Could not resolve proxy name"; @@ -331,8 +324,7 @@ curl_easy_strerror(CURLcode error) #endif } -const char * -curl_multi_strerror(CURLMcode error) +const char *curl_multi_strerror(CURLMcode error) { #ifndef CURL_DISABLE_VERBOSE_STRINGS switch(error) { @@ -391,8 +383,7 @@ curl_multi_strerror(CURLMcode error) #endif } -const char * -curl_share_strerror(CURLSHcode error) +const char *curl_share_strerror(CURLSHcode error) { #ifndef CURL_DISABLE_VERBOSE_STRINGS switch(error) { @@ -427,8 +418,7 @@ curl_share_strerror(CURLSHcode error) #endif } -const char * -curl_url_strerror(CURLUcode error) +const char *curl_url_strerror(CURLUcode error) { #ifndef CURL_DISABLE_VERBOSE_STRINGS switch(error) { @@ -562,96 +552,96 @@ const char *Curl_sspi_strerror(SECURITY_STATUS err, char *buf, size_t buflen) #ifndef CURL_DISABLE_VERBOSE_STRINGS switch(err) { - case SEC_E_OK: - txt = "No error"; - break; + case SEC_E_OK: + txt = "No error"; + 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); - SEC2TXT(SEC_E_BUFFER_TOO_SMALL); - SEC2TXT(SEC_E_CANNOT_INSTALL); - SEC2TXT(SEC_E_CANNOT_PACK); - SEC2TXT(SEC_E_CERT_EXPIRED); - SEC2TXT(SEC_E_CERT_UNKNOWN); - SEC2TXT(SEC_E_CERT_WRONG_USAGE); - SEC2TXT(SEC_E_CONTEXT_EXPIRED); - SEC2TXT(SEC_E_CROSSREALM_DELEGATION_FAILURE); - SEC2TXT(SEC_E_CRYPTO_SYSTEM_INVALID); - SEC2TXT(SEC_E_DECRYPT_FAILURE); - SEC2TXT(SEC_E_DELEGATION_POLICY); - SEC2TXT(SEC_E_DELEGATION_REQUIRED); - SEC2TXT(SEC_E_DOWNGRADE_DETECTED); - SEC2TXT(SEC_E_ENCRYPT_FAILURE); - SEC2TXT(SEC_E_ILLEGAL_MESSAGE); - SEC2TXT(SEC_E_INCOMPLETE_CREDENTIALS); - SEC2TXT(SEC_E_INCOMPLETE_MESSAGE); - SEC2TXT(SEC_E_INSUFFICIENT_MEMORY); - SEC2TXT(SEC_E_INTERNAL_ERROR); - SEC2TXT(SEC_E_INVALID_HANDLE); - SEC2TXT(SEC_E_INVALID_PARAMETER); - SEC2TXT(SEC_E_INVALID_TOKEN); - SEC2TXT(SEC_E_ISSUING_CA_UNTRUSTED); - SEC2TXT(SEC_E_ISSUING_CA_UNTRUSTED_KDC); - SEC2TXT(SEC_E_KDC_CERT_EXPIRED); - SEC2TXT(SEC_E_KDC_CERT_REVOKED); - SEC2TXT(SEC_E_KDC_INVALID_REQUEST); - SEC2TXT(SEC_E_KDC_UNABLE_TO_REFER); - SEC2TXT(SEC_E_KDC_UNKNOWN_ETYPE); - SEC2TXT(SEC_E_LOGON_DENIED); - SEC2TXT(SEC_E_MAX_REFERRALS_EXCEEDED); - SEC2TXT(SEC_E_MESSAGE_ALTERED); - SEC2TXT(SEC_E_MULTIPLE_ACCOUNTS); - SEC2TXT(SEC_E_MUST_BE_KDC); - SEC2TXT(SEC_E_NOT_OWNER); - SEC2TXT(SEC_E_NO_AUTHENTICATING_AUTHORITY); - SEC2TXT(SEC_E_NO_CREDENTIALS); - SEC2TXT(SEC_E_NO_IMPERSONATION); - SEC2TXT(SEC_E_NO_IP_ADDRESSES); - SEC2TXT(SEC_E_NO_KERB_KEY); - SEC2TXT(SEC_E_NO_PA_DATA); - SEC2TXT(SEC_E_NO_S4U_PROT_SUPPORT); - SEC2TXT(SEC_E_NO_TGT_REPLY); - SEC2TXT(SEC_E_OUT_OF_SEQUENCE); - SEC2TXT(SEC_E_PKINIT_CLIENT_FAILURE); - SEC2TXT(SEC_E_PKINIT_NAME_MISMATCH); - SEC2TXT(SEC_E_POLICY_NLTM_ONLY); - SEC2TXT(SEC_E_QOP_NOT_SUPPORTED); - SEC2TXT(SEC_E_REVOCATION_OFFLINE_C); - SEC2TXT(SEC_E_REVOCATION_OFFLINE_KDC); - SEC2TXT(SEC_E_SECPKG_NOT_FOUND); - SEC2TXT(SEC_E_SECURITY_QOS_FAILED); - SEC2TXT(SEC_E_SHUTDOWN_IN_PROGRESS); - SEC2TXT(SEC_E_SMARTCARD_CERT_EXPIRED); - SEC2TXT(SEC_E_SMARTCARD_CERT_REVOKED); - SEC2TXT(SEC_E_SMARTCARD_LOGON_REQUIRED); - SEC2TXT(SEC_E_STRONG_CRYPTO_NOT_SUPPORTED); - SEC2TXT(SEC_E_TARGET_UNKNOWN); - SEC2TXT(SEC_E_TIME_SKEW); - SEC2TXT(SEC_E_TOO_MANY_PRINCIPALS); - SEC2TXT(SEC_E_UNFINISHED_CONTEXT_DELETED); - SEC2TXT(SEC_E_UNKNOWN_CREDENTIALS); - SEC2TXT(SEC_E_UNSUPPORTED_FUNCTION); - SEC2TXT(SEC_E_UNSUPPORTED_PREAUTH); - SEC2TXT(SEC_E_UNTRUSTED_ROOT); - SEC2TXT(SEC_E_WRONG_CREDENTIAL_HANDLE); - SEC2TXT(SEC_E_WRONG_PRINCIPAL); - SEC2TXT(SEC_I_COMPLETE_AND_CONTINUE); - SEC2TXT(SEC_I_COMPLETE_NEEDED); - SEC2TXT(SEC_I_CONTEXT_EXPIRED); - SEC2TXT(SEC_I_CONTINUE_NEEDED); - SEC2TXT(SEC_I_INCOMPLETE_CREDENTIALS); - SEC2TXT(SEC_I_LOCAL_LOGON); - SEC2TXT(SEC_I_NO_LSA_CONTEXT); - SEC2TXT(SEC_I_RENEGOTIATE); - SEC2TXT(SEC_I_SIGNATURE_NEEDED); - default: - txt = "Unknown error"; + 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); + SEC2TXT(SEC_E_BUFFER_TOO_SMALL); + SEC2TXT(SEC_E_CANNOT_INSTALL); + SEC2TXT(SEC_E_CANNOT_PACK); + SEC2TXT(SEC_E_CERT_EXPIRED); + SEC2TXT(SEC_E_CERT_UNKNOWN); + SEC2TXT(SEC_E_CERT_WRONG_USAGE); + SEC2TXT(SEC_E_CONTEXT_EXPIRED); + SEC2TXT(SEC_E_CROSSREALM_DELEGATION_FAILURE); + SEC2TXT(SEC_E_CRYPTO_SYSTEM_INVALID); + SEC2TXT(SEC_E_DECRYPT_FAILURE); + SEC2TXT(SEC_E_DELEGATION_POLICY); + SEC2TXT(SEC_E_DELEGATION_REQUIRED); + SEC2TXT(SEC_E_DOWNGRADE_DETECTED); + SEC2TXT(SEC_E_ENCRYPT_FAILURE); + SEC2TXT(SEC_E_ILLEGAL_MESSAGE); + SEC2TXT(SEC_E_INCOMPLETE_CREDENTIALS); + SEC2TXT(SEC_E_INCOMPLETE_MESSAGE); + SEC2TXT(SEC_E_INSUFFICIENT_MEMORY); + SEC2TXT(SEC_E_INTERNAL_ERROR); + SEC2TXT(SEC_E_INVALID_HANDLE); + SEC2TXT(SEC_E_INVALID_PARAMETER); + SEC2TXT(SEC_E_INVALID_TOKEN); + SEC2TXT(SEC_E_ISSUING_CA_UNTRUSTED); + SEC2TXT(SEC_E_ISSUING_CA_UNTRUSTED_KDC); + SEC2TXT(SEC_E_KDC_CERT_EXPIRED); + SEC2TXT(SEC_E_KDC_CERT_REVOKED); + SEC2TXT(SEC_E_KDC_INVALID_REQUEST); + SEC2TXT(SEC_E_KDC_UNABLE_TO_REFER); + SEC2TXT(SEC_E_KDC_UNKNOWN_ETYPE); + SEC2TXT(SEC_E_LOGON_DENIED); + SEC2TXT(SEC_E_MAX_REFERRALS_EXCEEDED); + SEC2TXT(SEC_E_MESSAGE_ALTERED); + SEC2TXT(SEC_E_MULTIPLE_ACCOUNTS); + SEC2TXT(SEC_E_MUST_BE_KDC); + SEC2TXT(SEC_E_NOT_OWNER); + SEC2TXT(SEC_E_NO_AUTHENTICATING_AUTHORITY); + SEC2TXT(SEC_E_NO_CREDENTIALS); + SEC2TXT(SEC_E_NO_IMPERSONATION); + SEC2TXT(SEC_E_NO_IP_ADDRESSES); + SEC2TXT(SEC_E_NO_KERB_KEY); + SEC2TXT(SEC_E_NO_PA_DATA); + SEC2TXT(SEC_E_NO_S4U_PROT_SUPPORT); + SEC2TXT(SEC_E_NO_TGT_REPLY); + SEC2TXT(SEC_E_OUT_OF_SEQUENCE); + SEC2TXT(SEC_E_PKINIT_CLIENT_FAILURE); + SEC2TXT(SEC_E_PKINIT_NAME_MISMATCH); + SEC2TXT(SEC_E_POLICY_NLTM_ONLY); + SEC2TXT(SEC_E_QOP_NOT_SUPPORTED); + SEC2TXT(SEC_E_REVOCATION_OFFLINE_C); + SEC2TXT(SEC_E_REVOCATION_OFFLINE_KDC); + SEC2TXT(SEC_E_SECPKG_NOT_FOUND); + SEC2TXT(SEC_E_SECURITY_QOS_FAILED); + SEC2TXT(SEC_E_SHUTDOWN_IN_PROGRESS); + SEC2TXT(SEC_E_SMARTCARD_CERT_EXPIRED); + SEC2TXT(SEC_E_SMARTCARD_CERT_REVOKED); + SEC2TXT(SEC_E_SMARTCARD_LOGON_REQUIRED); + SEC2TXT(SEC_E_STRONG_CRYPTO_NOT_SUPPORTED); + SEC2TXT(SEC_E_TARGET_UNKNOWN); + SEC2TXT(SEC_E_TIME_SKEW); + SEC2TXT(SEC_E_TOO_MANY_PRINCIPALS); + SEC2TXT(SEC_E_UNFINISHED_CONTEXT_DELETED); + SEC2TXT(SEC_E_UNKNOWN_CREDENTIALS); + SEC2TXT(SEC_E_UNSUPPORTED_FUNCTION); + SEC2TXT(SEC_E_UNSUPPORTED_PREAUTH); + SEC2TXT(SEC_E_UNTRUSTED_ROOT); + SEC2TXT(SEC_E_WRONG_CREDENTIAL_HANDLE); + SEC2TXT(SEC_E_WRONG_PRINCIPAL); + SEC2TXT(SEC_I_COMPLETE_AND_CONTINUE); + SEC2TXT(SEC_I_COMPLETE_NEEDED); + SEC2TXT(SEC_I_CONTEXT_EXPIRED); + SEC2TXT(SEC_I_CONTINUE_NEEDED); + SEC2TXT(SEC_I_INCOMPLETE_CREDENTIALS); + SEC2TXT(SEC_I_LOCAL_LOGON); + SEC2TXT(SEC_I_NO_LSA_CONTEXT); + SEC2TXT(SEC_I_RENEGOTIATE); + SEC2TXT(SEC_I_SIGNATURE_NEEDED); + default: + txt = "Unknown error"; } if(err == SEC_E_ILLEGAL_MESSAGE) { @@ -674,12 +664,11 @@ const char *Curl_sspi_strerror(SECURITY_STATUS err, char *buf, size_t buflen) txt = "No error"; else txt = "Error"; - if(buflen > strlen(txt)) - strcpy(buf, txt); + curlx_strcopy(buf, buflen, txt, strlen(txt)); #endif if(errno != old_errno) - CURL_SETERRNO(old_errno); + errno = old_errno; #ifdef _WIN32 if(old_win_err != GetLastError()) diff --git a/lib/strerror.h b/lib/strerror.h index c52503ed9316..a10164c9da0b 100644 --- a/lib/strerror.h +++ b/lib/strerror.h @@ -24,6 +24,8 @@ * ***************************************************************************/ +#include "curl_setup.h" + #ifdef USE_WINDOWS_SSPI const char *Curl_sspi_strerror(SECURITY_STATUS err, char *buf, size_t buflen); #endif diff --git a/lib/system_win32.c b/lib/system_win32.c index cd01fd2ebfe3..a53f61724e09 100644 --- a/lib/system_win32.c +++ b/lib/system_win32.c @@ -26,15 +26,9 @@ #ifdef _WIN32 -#include #include "system_win32.h" #include "curlx/version_win32.h" #include "curl_sspi.h" -#include "curlx/warnless.h" - -/* The last #include files should be: */ -#include "curl_memory.h" -#include "memdebug.h" #ifndef HAVE_IF_NAMETOINDEX /* Handle of iphlpapp.dll */ @@ -74,7 +68,7 @@ CURLcode Curl_win32_init(long flags) /* highest supported version. */ if(LOBYTE(wsaData.wVersion) != LOBYTE(wVersionRequested) || - HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested) ) { + HIBYTE(wsaData.wVersion) != HIBYTE(wVersionRequested)) { /* Tell the user that we could not find a usable */ /* winsock.dll. */ @@ -99,15 +93,9 @@ CURLcode Curl_win32_init(long flags) s_hIpHlpApiDll = curl_load_library(TEXT("iphlpapi.dll")); if(s_hIpHlpApiDll) { /* Get the address of the if_nametoindex function */ -#ifdef UNDER_CE - #define CURL_TEXT(n) TEXT(n) -#else - #define CURL_TEXT(n) (n) -#endif IF_NAMETOINDEX_FN pIfNameToIndex = CURLX_FUNCTION_CAST(IF_NAMETOINDEX_FN, - GetProcAddress(s_hIpHlpApiDll, - CURL_TEXT("if_nametoindex"))); + GetProcAddress(s_hIpHlpApiDll, "if_nametoindex")); if(pIfNameToIndex) Curl_if_nametoindex = pIfNameToIndex; @@ -164,13 +152,9 @@ typedef HMODULE (APIENTRY *LOADLIBRARYEX_FN)(LPCTSTR, HANDLE, DWORD); /* See function definitions in winbase.h */ #ifdef UNICODE -# ifdef UNDER_CE -# define LOADLIBARYEX L"LoadLibraryExW" -# else -# define LOADLIBARYEX "LoadLibraryExW" -# endif +# define LOADLIBARYEX "LoadLibraryExW" #else -# define LOADLIBARYEX "LoadLibraryExA" +# define LOADLIBARYEX "LoadLibraryExA" #endif /* @@ -189,7 +173,7 @@ typedef HMODULE (APIENTRY *LOADLIBRARYEX_FN)(LPCTSTR, HANDLE, DWORD); */ static HMODULE curl_load_library(LPCTSTR filename) { -#if !defined(CURL_WINDOWS_UWP) && !defined(UNDER_CE) +#ifndef CURL_WINDOWS_UWP HMODULE hModule = NULL; LOADLIBRARYEX_FN pLoadLibraryEx = NULL; @@ -228,7 +212,8 @@ static HMODULE curl_load_library(LPCTSTR filename) /* Allocate space for the full DLL path (Room for the null-terminator is included in systemdirlen) */ size_t filenamelen = _tcslen(filename); - TCHAR *path = malloc(sizeof(TCHAR) * (systemdirlen + 1 + filenamelen)); + TCHAR *path = curlx_malloc(sizeof(TCHAR) * + (systemdirlen + 1 + filenamelen)); if(path && GetSystemDirectory(path, systemdirlen)) { /* Calculate the full DLL path */ _tcscpy(path + _tcslen(path), TEXT("\\")); @@ -240,7 +225,7 @@ static HMODULE curl_load_library(LPCTSTR filename) pLoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) : LoadLibrary(path); } - free(path); + curlx_free(path); } } return hModule; diff --git a/lib/system_win32.h b/lib/system_win32.h index 6bf89d3d9d77..e3ed0547fed2 100644 --- a/lib/system_win32.h +++ b/lib/system_win32.h @@ -28,8 +28,6 @@ #ifdef _WIN32 -#include - extern LARGE_INTEGER Curl_freq; extern bool Curl_isVistaOrGreater; diff --git a/lib/telnet.c b/lib/telnet.c index 5c25bc2eaa36..b4589158e9df 100644 --- a/lib/telnet.c +++ b/lib/telnet.c @@ -48,45 +48,39 @@ #include "urldata.h" #include "url.h" -#include #include "transfer.h" #include "sendf.h" +#include "curl_trc.h" #include "telnet.h" #include "connect.h" #include "progress.h" -#include "system_win32.h" #include "arpa_telnet.h" #include "select.h" -#include "curlx/warnless.h" #include "curlx/strparse.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - #define SUBBUFSIZE 512 -#define CURL_SB_CLEAR(x) x->subpointer = x->subbuffer -#define CURL_SB_TERM(x) \ - do { \ - x->subend = x->subpointer; \ - CURL_SB_CLEAR(x); \ +#define CURL_SB_CLEAR(x) x->subpointer = x->subbuffer +#define CURL_SB_TERM(x) \ + do { \ + x->subend = x->subpointer; \ + CURL_SB_CLEAR(x); \ } while(0) -#define CURL_SB_ACCUM(x,c) \ - do { \ - if(x->subpointer < (x->subbuffer + sizeof(x->subbuffer))) \ - *x->subpointer++ = (c); \ +#define CURL_SB_ACCUM(x, c) \ + do { \ + if(x->subpointer < (x->subbuffer + sizeof(x->subbuffer))) \ + *x->subpointer++ = (c); \ } while(0) -#define CURL_SB_GET(x) ((*x->subpointer++)&0xff) -#define CURL_SB_LEN(x) (x->subend - x->subpointer) +#define CURL_SB_GET(x) ((*x->subpointer++) & 0xff) +#define CURL_SB_LEN(x) (x->subend - x->subpointer) /* For posterity: #define CURL_SB_PEEK(x) ((*x->subpointer)&0xff) #define CURL_SB_EOF(x) (x->subpointer >= x->subend) */ #ifdef CURL_DISABLE_VERBOSE_STRINGS -#define printoption(a,b,c,d) Curl_nop_stmt +#define printoption(a, b, c, d) Curl_nop_stmt #endif /* For negotiation compliant to RFC 1143 */ @@ -98,15 +92,13 @@ #define CURL_EMPTY 0 #define CURL_OPPOSITE 1 - /* meta key for storing protocol meta at easy handle */ #define CURL_META_TELNET_EASY "meta:proto:telnet:easy" /* * Telnet receiver states for fsm */ -typedef enum -{ +typedef enum { CURL_TS_DATA = 0, CURL_TS_IAC, CURL_TS_WILL, @@ -141,12 +133,12 @@ struct TELNET { unsigned char *subpointer, *subend; /* buffer for sub-options */ }; - -static -CURLcode telrcv(struct Curl_easy *data, - struct TELNET *tn, - const unsigned char *inbuf, /* Data received from socket */ - ssize_t count); /* Number of bytes received */ +static CURLcode telrcv(struct Curl_easy *data, + struct TELNET *tn, + const unsigned char *inbuf, /* Data received from + socket */ + ssize_t count); /* Number of bytes + received */ #ifndef CURL_DISABLE_VERBOSE_STRINGS static void printoption(struct Curl_easy *data, @@ -203,7 +195,6 @@ const struct Curl_handler Curl_handler_telnet = { PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */ }; - static void telnet_easy_dtor(void *key, size_t klen, void *entry) { struct TELNET *tn = entry; @@ -211,15 +202,14 @@ static void telnet_easy_dtor(void *key, size_t klen, void *entry) (void)klen; curl_slist_free_all(tn->telnet_vars); curlx_dyn_free(&tn->out); - free(tn); + curlx_free(tn); } -static -CURLcode init_telnet(struct Curl_easy *data) +static CURLcode init_telnet(struct Curl_easy *data) { struct TELNET *tn; - tn = calloc(1, sizeof(struct TELNET)); + tn = curlx_calloc(1, sizeof(struct TELNET)); if(!tn) return CURLE_OUT_OF_MEMORY; @@ -332,15 +322,14 @@ static void send_negotiation(struct Curl_easy *data, int cmd, int option) bytes_written = swrite(conn->sock[FIRSTSOCKET], buf, 3); if(bytes_written < 0) { int err = SOCKERRNO; - failf(data,"Sending data failed (%d)",err); + failf(data, "Sending data failed (%d)", err); } printoption(data, "SENT", cmd, option); } -static -void set_remote_option(struct Curl_easy *data, struct TELNET *tn, - int option, int newstate) +static void set_remote_option(struct Curl_easy *data, struct TELNET *tn, + int option, int newstate) { if(newstate == CURL_YES) { switch(tn->him[option]) { @@ -412,8 +401,7 @@ void set_remote_option(struct Curl_easy *data, struct TELNET *tn, } } -static -void rec_will(struct Curl_easy *data, struct TELNET *tn, int option) +static void rec_will(struct Curl_easy *data, struct TELNET *tn, int option) { switch(tn->him[option]) { case CURL_NO: @@ -459,8 +447,7 @@ void rec_will(struct Curl_easy *data, struct TELNET *tn, int option) } } -static -void rec_wont(struct Curl_easy *data, struct TELNET *tn, int option) +static void rec_wont(struct Curl_easy *data, struct TELNET *tn, int option) { switch(tn->him[option]) { case CURL_NO: @@ -500,9 +487,8 @@ void rec_wont(struct Curl_easy *data, struct TELNET *tn, int option) } } -static void -set_local_option(struct Curl_easy *data, struct TELNET *tn, - int option, int newstate) +static void set_local_option(struct Curl_easy *data, struct TELNET *tn, + int option, int newstate) { if(newstate == CURL_YES) { switch(tn->us[option]) { @@ -574,8 +560,7 @@ set_local_option(struct Curl_easy *data, struct TELNET *tn, } } -static -void rec_do(struct Curl_easy *data, struct TELNET *tn, int option) +static void rec_do(struct Curl_easy *data, struct TELNET *tn, int option) { switch(tn->us[option]) { case CURL_NO: @@ -633,8 +618,7 @@ void rec_do(struct Curl_easy *data, struct TELNET *tn, int option) } } -static -void rec_dont(struct Curl_easy *data, struct TELNET *tn, int option) +static void rec_dont(struct Curl_easy *data, struct TELNET *tn, int option) { switch(tn->us[option]) { case CURL_NO: @@ -674,7 +658,6 @@ void rec_dont(struct Curl_easy *data, struct TELNET *tn, int option) } } - static void printsub(struct Curl_easy *data, int direction, /* '<' or '>' */ unsigned char *pointer, /* where suboption data is */ @@ -687,8 +670,8 @@ static void printsub(struct Curl_easy *data, if(length >= 3) { int j; - i = pointer[length-2]; - j = pointer[length-1]; + i = pointer[length - 2]; + j = pointer[length - 1]; if(i != CURL_IAC || j != CURL_SE) { infof(data, "(terminated by "); @@ -895,8 +878,10 @@ static CURLcode check_telnet_options(struct Curl_easy *data, case 6: /* To take care or not of the 8th bit in data exchange */ if(curl_strnequal(option, "BINARY", 6)) { - int binary_option = atoi(arg); - if(binary_option != 1) { + const char *p = arg; + curl_off_t binary_option; + if(!curlx_str_number(&p, &binary_option, 1) && + (binary_option != 1)) { tn->us_preferred[CURL_TELOPT_BINARY] = CURL_NO; tn->him_preferred[CURL_TELOPT_BINARY] = CURL_NO; } @@ -952,77 +937,77 @@ static CURLcode suboption(struct Curl_easy *data, struct TELNET *tn) printsub(data, '<', (unsigned char *)tn->subbuffer, CURL_SB_LEN(tn) + 2); switch(CURL_SB_GET(tn)) { - case CURL_TELOPT_TTYPE: - if(bad_option(tn->subopt_ttype)) - return CURLE_BAD_FUNCTION_ARGUMENT; - if(strlen(tn->subopt_ttype) > 1000) { - failf(data, "Tool long telnet TTYPE"); - return CURLE_SEND_ERROR; - } - len = curl_msnprintf((char *)temp, sizeof(temp), "%c%c%c%c%s%c%c", - CURL_IAC, CURL_SB, CURL_TELOPT_TTYPE, - CURL_TELQUAL_IS, tn->subopt_ttype, CURL_IAC, - CURL_SE); - bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len); + case CURL_TELOPT_TTYPE: + if(bad_option(tn->subopt_ttype)) + return CURLE_BAD_FUNCTION_ARGUMENT; + if(strlen(tn->subopt_ttype) > 1000) { + failf(data, "Tool long telnet TTYPE"); + return CURLE_SEND_ERROR; + } + len = curl_msnprintf((char *)temp, sizeof(temp), "%c%c%c%c%s%c%c", + CURL_IAC, CURL_SB, CURL_TELOPT_TTYPE, + CURL_TELQUAL_IS, tn->subopt_ttype, CURL_IAC, + CURL_SE); + bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len); - if(bytes_written < 0) { - err = SOCKERRNO; - failf(data, "Sending data failed (%d)", err); - return CURLE_SEND_ERROR; - } - printsub(data, '>', &temp[2], len-2); - break; - case CURL_TELOPT_XDISPLOC: - if(bad_option(tn->subopt_xdisploc)) + if(bytes_written < 0) { + err = SOCKERRNO; + failf(data, "Sending data failed (%d)", err); + return CURLE_SEND_ERROR; + } + printsub(data, '>', &temp[2], len-2); + break; + case CURL_TELOPT_XDISPLOC: + if(bad_option(tn->subopt_xdisploc)) + return CURLE_BAD_FUNCTION_ARGUMENT; + if(strlen(tn->subopt_xdisploc) > 1000) { + failf(data, "Tool long telnet XDISPLOC"); + return CURLE_SEND_ERROR; + } + len = curl_msnprintf((char *)temp, sizeof(temp), "%c%c%c%c%s%c%c", + CURL_IAC, CURL_SB, CURL_TELOPT_XDISPLOC, + CURL_TELQUAL_IS, tn->subopt_xdisploc, CURL_IAC, + CURL_SE); + bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len); + if(bytes_written < 0) { + err = SOCKERRNO; + failf(data, "Sending data failed (%d)", err); + return CURLE_SEND_ERROR; + } + printsub(data, '>', &temp[2], len - 2); + break; + case CURL_TELOPT_NEW_ENVIRON: + len = curl_msnprintf((char *)temp, sizeof(temp), "%c%c%c%c", + CURL_IAC, CURL_SB, CURL_TELOPT_NEW_ENVIRON, + CURL_TELQUAL_IS); + for(v = tn->telnet_vars; v; v = v->next) { + size_t tmplen = (strlen(v->data) + 1); + if(bad_option(v->data)) return CURLE_BAD_FUNCTION_ARGUMENT; - if(strlen(tn->subopt_xdisploc) > 1000) { - failf(data, "Tool long telnet XDISPLOC"); - return CURLE_SEND_ERROR; - } - len = curl_msnprintf((char *)temp, sizeof(temp), "%c%c%c%c%s%c%c", - CURL_IAC, CURL_SB, CURL_TELOPT_XDISPLOC, - CURL_TELQUAL_IS, tn->subopt_xdisploc, CURL_IAC, - CURL_SE); - bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len); - if(bytes_written < 0) { - err = SOCKERRNO; - failf(data,"Sending data failed (%d)",err); - return CURLE_SEND_ERROR; - } - printsub(data, '>', &temp[2], len-2); - break; - case CURL_TELOPT_NEW_ENVIRON: - len = curl_msnprintf((char *)temp, sizeof(temp), "%c%c%c%c", - CURL_IAC, CURL_SB, CURL_TELOPT_NEW_ENVIRON, - CURL_TELQUAL_IS); - for(v = tn->telnet_vars; v; v = v->next) { - size_t tmplen = (strlen(v->data) + 1); - if(bad_option(v->data)) - return CURLE_BAD_FUNCTION_ARGUMENT; - /* Add the variable if it fits */ - if(len + tmplen < (int)sizeof(temp)-6) { - char *s = strchr(v->data, ','); - if(!s) - len += curl_msnprintf((char *)&temp[len], sizeof(temp) - len, - "%c%s", CURL_NEW_ENV_VAR, v->data); - else { - size_t vlen = s - v->data; - len += curl_msnprintf((char *)&temp[len], sizeof(temp) - len, - "%c%.*s%c%s", CURL_NEW_ENV_VAR, - (int)vlen, v->data, CURL_NEW_ENV_VALUE, ++s); - } + /* Add the variable if it fits */ + if(len + tmplen < (int)sizeof(temp) - 6) { + char *s = strchr(v->data, ','); + if(!s) + len += curl_msnprintf((char *)&temp[len], sizeof(temp) - len, + "%c%s", CURL_NEW_ENV_VAR, v->data); + else { + size_t vlen = s - v->data; + len += curl_msnprintf((char *)&temp[len], sizeof(temp) - len, + "%c%.*s%c%s", CURL_NEW_ENV_VAR, + (int)vlen, v->data, CURL_NEW_ENV_VALUE, ++s); } } - curl_msnprintf((char *)&temp[len], sizeof(temp) - len, - "%c%c", CURL_IAC, CURL_SE); - len += 2; - bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len); - if(bytes_written < 0) { - err = SOCKERRNO; - failf(data,"Sending data failed (%d)",err); - } - printsub(data, '>', &temp[2], len-2); - break; + } + curl_msnprintf((char *)&temp[len], sizeof(temp) - len, + "%c%c", CURL_IAC, CURL_SE); + len += 2; + bytes_written = swrite(conn->sock[FIRSTSOCKET], temp, len); + if(bytes_written < 0) { + err = SOCKERRNO; + failf(data, "Sending data failed (%d)", err); + } + printsub(data, '>', &temp[2], len - 2); + break; } return CURLE_OK; } @@ -1065,7 +1050,7 @@ static void sendsuboption(struct Curl_easy *data, /* data suboption is now ready */ printsub(data, '>', (unsigned char *)tn->subbuffer + 2, - CURL_SB_LEN(tn)-2); + CURL_SB_LEN(tn) - 2); /* we send the header of the suboption... */ bytes_written = swrite(conn->sock[FIRSTSOCKET], tn->subbuffer, 3); @@ -1086,11 +1071,12 @@ static void sendsuboption(struct Curl_easy *data, } } -static -CURLcode telrcv(struct Curl_easy *data, - struct TELNET *tn, - const unsigned char *inbuf, /* Data received from socket */ - ssize_t count) /* Number of bytes received */ +static CURLcode telrcv(struct Curl_easy *data, + struct TELNET *tn, + const unsigned char *inbuf, /* Data received from + socket */ + ssize_t count) /* Number of bytes + received */ { unsigned char c; CURLcode result; @@ -1108,9 +1094,9 @@ CURLcode telrcv(struct Curl_easy *data, } \ startwrite = -1 -#define writebyte() \ - if(startwrite < 0) \ - startwrite = in +#define writebyte() \ + if(startwrite < 0) \ + startwrite = in #define bufferflush() startskipping() @@ -1172,79 +1158,79 @@ CURLcode telrcv(struct Curl_easy *data, } break; - case CURL_TS_WILL: - printoption(data, "RCVD", CURL_WILL, c); - tn->please_negotiate = 1; - rec_will(data, tn, c); - tn->telrcv_state = CURL_TS_DATA; - break; + case CURL_TS_WILL: + printoption(data, "RCVD", CURL_WILL, c); + tn->please_negotiate = 1; + rec_will(data, tn, c); + tn->telrcv_state = CURL_TS_DATA; + break; - case CURL_TS_WONT: - printoption(data, "RCVD", CURL_WONT, c); - tn->please_negotiate = 1; - rec_wont(data, tn, c); - tn->telrcv_state = CURL_TS_DATA; - break; + case CURL_TS_WONT: + printoption(data, "RCVD", CURL_WONT, c); + tn->please_negotiate = 1; + rec_wont(data, tn, c); + tn->telrcv_state = CURL_TS_DATA; + break; - case CURL_TS_DO: - printoption(data, "RCVD", CURL_DO, c); - tn->please_negotiate = 1; - rec_do(data, tn, c); - tn->telrcv_state = CURL_TS_DATA; - break; + case CURL_TS_DO: + printoption(data, "RCVD", CURL_DO, c); + tn->please_negotiate = 1; + rec_do(data, tn, c); + tn->telrcv_state = CURL_TS_DATA; + break; - case CURL_TS_DONT: - printoption(data, "RCVD", CURL_DONT, c); - tn->please_negotiate = 1; - rec_dont(data, tn, c); - tn->telrcv_state = CURL_TS_DATA; - break; + case CURL_TS_DONT: + printoption(data, "RCVD", CURL_DONT, c); + tn->please_negotiate = 1; + rec_dont(data, tn, c); + tn->telrcv_state = CURL_TS_DATA; + break; - case CURL_TS_SB: - if(c == CURL_IAC) - tn->telrcv_state = CURL_TS_SE; - else - CURL_SB_ACCUM(tn, c); - break; + case CURL_TS_SB: + if(c == CURL_IAC) + tn->telrcv_state = CURL_TS_SE; + else + CURL_SB_ACCUM(tn, c); + break; - case CURL_TS_SE: - if(c != CURL_SE) { - if(c != CURL_IAC) { - /* - * This is an error. We only expect to get "IAC IAC" or "IAC SE". - * Several things may have happened. An IAC was not doubled, the - * IAC SE was left off, or another option got inserted into the - * suboption are all possibilities. If we assume that the IAC was - * not doubled, and really the IAC SE was left off, we could get - * into an infinite loop here. So, instead, we terminate the - * suboption, and process the partial suboption if we can. - */ - CURL_SB_ACCUM(tn, CURL_IAC); - CURL_SB_ACCUM(tn, c); - tn->subpointer -= 2; - CURL_SB_TERM(tn); - - printoption(data, "In SUBOPTION processing, RCVD", CURL_IAC, c); - result = suboption(data, tn); /* handle sub-option */ - if(result) - return result; - tn->telrcv_state = CURL_TS_IAC; - goto process_iac; - } - CURL_SB_ACCUM(tn, c); - tn->telrcv_state = CURL_TS_SB; - } - else { + case CURL_TS_SE: + if(c != CURL_SE) { + if(c != CURL_IAC) { + /* + * This is an error. We only expect to get "IAC IAC" or "IAC SE". + * Several things may have happened. An IAC was not doubled, the + * IAC SE was left off, or another option got inserted into the + * suboption are all possibilities. If we assume that the IAC was + * not doubled, and really the IAC SE was left off, we could get + * into an infinite loop here. So, instead, we terminate the + * suboption, and process the partial suboption if we can. + */ CURL_SB_ACCUM(tn, CURL_IAC); - CURL_SB_ACCUM(tn, CURL_SE); + CURL_SB_ACCUM(tn, c); tn->subpointer -= 2; CURL_SB_TERM(tn); + + printoption(data, "In SUBOPTION processing, RCVD", CURL_IAC, c); result = suboption(data, tn); /* handle sub-option */ if(result) return result; - tn->telrcv_state = CURL_TS_DATA; + tn->telrcv_state = CURL_TS_IAC; + goto process_iac; } - break; + CURL_SB_ACCUM(tn, c); + tn->telrcv_state = CURL_TS_SB; + } + else { + CURL_SB_ACCUM(tn, CURL_IAC); + CURL_SB_ACCUM(tn, CURL_SE); + tn->subpointer -= 2; + CURL_SB_TERM(tn); + result = suboption(data, tn); /* handle sub-option */ + if(result) + return result; + tn->telrcv_state = CURL_TS_DATA; + } + break; } ++in; } @@ -1293,16 +1279,16 @@ static CURLcode send_telnet_data(struct Curl_easy *data, pfd[0].fd = conn->sock[FIRSTSOCKET]; pfd[0].events = POLLOUT; switch(Curl_poll(pfd, 1, -1)) { - case -1: /* error, abort writing */ - case 0: /* timeout (will never happen) */ - result = CURLE_SEND_ERROR; - break; - default: /* write! */ - bytes_written = 0; - result = Curl_xfer_send(data, outbuf + total_written, - outlen - total_written, FALSE, &bytes_written); - total_written += bytes_written; - break; + case -1: /* error, abort writing */ + case 0: /* timeout (will never happen) */ + result = CURLE_SEND_ERROR; + break; + default: /* write! */ + bytes_written = 0; + result = Curl_xfer_send(data, outbuf + total_written, + outlen - total_written, FALSE, &bytes_written); + total_written += bytes_written; + break; } } @@ -1328,21 +1314,18 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done) WSANETWORKEVENTS events; HANDLE stdin_handle; HANDLE objs[2]; - DWORD obj_count; - DWORD wait_timeout; + DWORD obj_count; + DWORD wait_timeout; DWORD readfile_read; int err; #else timediff_t interval_ms; struct pollfd pfd[2]; int poll_cnt; - curl_off_t total_dl = 0; - curl_off_t total_ul = 0; ssize_t snread; #endif - struct curltime now; bool keepon = TRUE; - char buffer[4*1024]; + char buffer[4 * 1024]; struct TELNET *tn; *done = TRUE; /* unconditionally */ @@ -1373,7 +1356,8 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done) } /* Tell Winsock what events we want to listen to */ - if(WSAEventSelect(sockfd, event_handle, FD_READ|FD_CLOSE) == SOCKET_ERROR) { + if(WSAEventSelect(sockfd, event_handle, FD_READ | FD_CLOSE) == + SOCKET_ERROR) { WSACloseEvent(event_handle); return CURLE_RECV_ERROR; } @@ -1387,8 +1371,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done) /* If stdin_handle is a pipe, use PeekNamedPipe() method to check it, else use the old WaitForMultipleObjects() way */ - if(GetFileType(stdin_handle) == FILE_TYPE_PIPE || - data->set.is_fread_set) { + if(GetFileType(stdin_handle) == FILE_TYPE_PIPE || data->set.is_fread_set) { /* Do not wait for stdin_handle, just wait for event_handle */ obj_count = 1; /* Check stdin_handle per 100 milliseconds */ @@ -1406,8 +1389,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done) FALSE, wait_timeout); switch(waitret) { - case WAIT_TIMEOUT: - { + case WAIT_TIMEOUT: { for(;;) { if(data->set.is_fread_set) { size_t n; @@ -1440,8 +1422,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done) if(!readfile_read) break; - if(!ReadFile(stdin_handle, buffer, buf_size, - &readfile_read, NULL)) { + if(!ReadFile(stdin_handle, buffer, buf_size, &readfile_read, NULL)) { keepon = FALSE; result = CURLE_READ_ERROR; break; @@ -1457,10 +1438,8 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done) } break; - case WAIT_OBJECT_0 + 1: - { - if(!ReadFile(stdin_handle, buffer, buf_size, - &readfile_read, NULL)) { + case WAIT_OBJECT_0 + 1: { + if(!ReadFile(stdin_handle, buffer, buf_size, &readfile_read, NULL)) { keepon = FALSE; result = CURLE_READ_ERROR; break; @@ -1474,8 +1453,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done) } break; - case WAIT_OBJECT_0: - { + case WAIT_OBJECT_0: { events.lNetworkEvents = 0; if(WSAEnumNetworkEvents(sockfd, event_handle, &events) == SOCKET_ERROR) { err = SOCKERRNO; @@ -1505,7 +1483,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done) break; } - result = telrcv(data, tn, (unsigned char *) buffer, nread); + result = telrcv(data, tn, (unsigned char *)buffer, nread); if(result) { keepon = FALSE; break; @@ -1522,14 +1500,13 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done) if(events.lNetworkEvents & FD_CLOSE) { keepon = FALSE; } + break; } - break; - - } + } /* switch */ if(data->set.timeout) { - now = curlx_now(); - if(curlx_timediff(now, conn->created) >= data->set.timeout) { + if(curlx_ptimediff_ms(Curl_pgrs_now(data), &conn->created) >= + data->set.timeout) { failf(data, "Time-out"); result = CURLE_OPERATION_TIMEDOUT; keepon = FALSE; @@ -1598,10 +1575,8 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done) break; } - total_dl += nread; - result = Curl_pgrsSetDownloadCounter(data, total_dl); - if(!result) - result = telrcv(data, tn, (unsigned char *)buffer, nread); + Curl_pgrs_download_inc(data, nread); + result = telrcv(data, tn, (unsigned char *)buffer, nread); if(result) { keepon = FALSE; break; @@ -1625,7 +1600,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done) else { /* read from user-supplied method */ snread = (int)data->state.fread_func(buffer, 1, sizeof(buffer), - data->state.in); + data->state.in); if(snread == CURL_READFUNC_ABORT) { keepon = FALSE; break; @@ -1640,8 +1615,7 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done) keepon = FALSE; break; } - total_ul += snread; - Curl_pgrsSetUploadCounter(data, total_ul); + Curl_pgrs_upload_inc(data, (size_t)snread); } else if(snread < 0) keepon = FALSE; @@ -1650,17 +1624,18 @@ static CURLcode telnet_do(struct Curl_easy *data, bool *done) } /* poll switch statement */ if(data->set.timeout) { - now = curlx_now(); - if(curlx_timediff(now, conn->created) >= data->set.timeout) { + if(curlx_ptimediff_ms(Curl_pgrs_now(data), &conn->created) >= + data->set.timeout) { failf(data, "Time-out"); result = CURLE_OPERATION_TIMEDOUT; keepon = FALSE; } } - if(Curl_pgrsUpdate(data)) { - result = CURLE_ABORTED_BY_CALLBACK; - break; + if(!result) { + result = Curl_pgrsUpdate(data); + if(result) + keepon = FALSE; } } #endif diff --git a/lib/tftp.c b/lib/tftp.c index d9d978c24e90..0e03933ab9a9 100644 --- a/lib/tftp.c +++ b/lib/tftp.c @@ -47,31 +47,26 @@ #endif #include "urldata.h" -#include #include "cfilters.h" #include "cf-socket.h" #include "transfer.h" #include "sendf.h" +#include "curl_trc.h" #include "tftp.h" #include "progress.h" #include "connect.h" #include "sockaddr.h" /* required for Curl_sockaddr_storage */ -#include "multiif.h" #include "url.h" #include "strcase.h" -#include "speedcheck.h" #include "select.h" #include "escape.h" #include "curlx/strerr.h" #include "curlx/strparse.h" - -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" +#include "curlx/strcopy.h" /* RFC2348 allows the block size to be negotiated */ #define TFTP_BLKSIZE_DEFAULT 512 -#define TFTP_OPTION_BLKSIZE "blksize" +#define TFTP_OPTION_BLKSIZE "blksize" /* from RFC2349: */ #define TFTP_OPTION_TSIZE "tsize" @@ -148,7 +143,6 @@ struct tftp_conn { BIT(remote_pinned); }; - /* Forward declarations */ static CURLcode tftp_rx(struct tftp_conn *state, tftp_event_t event); static CURLcode tftp_tx(struct tftp_conn *state, tftp_event_t event); @@ -164,11 +158,9 @@ static CURLcode tftp_pollset(struct Curl_easy *data, struct easy_pollset *ps); static CURLcode tftp_translate_code(tftp_error_t error); - /* * TFTP protocol handler. */ - const struct Curl_handler Curl_handler_tftp = { "tftp", /* scheme */ tftp_setup_connection, /* setup_connection */ @@ -211,7 +203,7 @@ static CURLcode tftp_set_timeouts(struct tftp_conn *state) bool start = (state->state == TFTP_STATE_START); /* Compute drop-dead time */ - timeout_ms = Curl_timeleft(state->data, NULL, start); + timeout_ms = Curl_timeleft_ms(state->data, start); if(timeout_ms < 0) { /* time-out, bail out, go home */ @@ -226,7 +218,7 @@ static CURLcode tftp_set_timeouts(struct tftp_conn *state) timeout = 15; /* Average reposting an ACK after 5 seconds */ - state->retry_max = (int)timeout/5; + state->retry_max = (int)timeout / 5; /* But bound the total number */ if(state->retry_max < 3) @@ -236,12 +228,12 @@ static CURLcode tftp_set_timeouts(struct tftp_conn *state) state->retry_max = 50; /* Compute the re-ACK interval to suit the timeout */ - state->retry_time = (int)(timeout/state->retry_max); + state->retry_time = (int)(timeout / state->retry_max); if(state->retry_time < 1) state->retry_time = 1; infof(state->data, - "set timeouts for state %d; Total % " FMT_OFF_T ", retry %d maxtry %d", + "set timeouts for state %d; Total %" FMT_OFF_T ", retry %d maxtry %d", (int)state->state, timeout_ms, state->retry_time, state->retry_max); /* init RX time */ @@ -264,7 +256,6 @@ static void setpacketevent(struct tftp_packet *packet, unsigned short num) packet->data[1] = (unsigned char)(num & 0xff); } - static void setpacketblock(struct tftp_packet *packet, unsigned short num) { packet->data[2] = (unsigned char)(num >> 8); @@ -284,7 +275,7 @@ static unsigned short getrpacketblock(const struct tftp_packet *packet) static size_t tftp_strnlen(const char *string, size_t maxlen) { const char *end = memchr(string, '\0', maxlen); - return end ? (size_t) (end - string) : maxlen; + return end ? (size_t)(end - string) : maxlen; } static const char *tftp_option_get(const char *buf, size_t len, @@ -299,7 +290,7 @@ static const char *tftp_option_get(const char *buf, size_t len, return NULL; *option = buf; - loc += tftp_strnlen(buf + loc, len-loc); + loc += tftp_strnlen(buf + loc, len - loc); loc++; /* NULL term */ if(loc > len) @@ -379,12 +370,17 @@ static CURLcode tftp_parse_option_ack(struct tftp_conn *state, } static CURLcode tftp_option_add(struct tftp_conn *state, size_t *csize, - char *buf, const char *option) + size_t index, const char *option) { - if(( strlen(option) + *csize + 1) > (size_t)state->blksize) + char *buf = (char *)&state->spacket.data[index]; + size_t oplen = strlen(option); + size_t blen; + if((state->blksize <= index) || + (oplen + 1) > (size_t)(state->blksize - index)) return CURLE_TFTP_ILLEGAL; - strcpy(buf, option); - *csize += strlen(option) + 1; + blen = state->blksize - index; + curlx_strcopy(buf, blen, option, oplen); + *csize += oplen + 1; return CURLE_OK; } @@ -471,14 +467,15 @@ static CURLcode tftp_send_first(struct tftp_conn *state, if(strlen(filename) > (state->blksize - strlen(mode) - 4)) { failf(data, "TFTP filename too long"); - free(filename); + curlx_free(filename); return CURLE_TFTP_ILLEGAL; /* too long filename field */ } curl_msnprintf((char *)state->spacket.data + 2, state->blksize, - "%s%c%s%c", filename, '\0', mode, '\0'); + "%s%c%s%c", filename, '\0', mode, '\0'); sbytes = 4 + strlen(filename) + strlen(mode); + curlx_free(filename); /* optional addition of TFTP options */ if(!data->set.tftp_no_options) { @@ -488,36 +485,26 @@ static CURLcode tftp_send_first(struct tftp_conn *state, data->state.upload && (data->state.infilesize != -1) ? data->state.infilesize : 0); - result = tftp_option_add(state, &sbytes, - (char *)state->spacket.data + sbytes, - TFTP_OPTION_TSIZE); + result = tftp_option_add(state, &sbytes, sbytes, TFTP_OPTION_TSIZE); if(result == CURLE_OK) - result = tftp_option_add(state, &sbytes, - (char *)state->spacket.data + sbytes, buf); + result = tftp_option_add(state, &sbytes, sbytes, buf); /* add blksize option */ curl_msnprintf(buf, sizeof(buf), "%d", state->requested_blksize); if(result == CURLE_OK) - result = tftp_option_add(state, &sbytes, - (char *)state->spacket.data + sbytes, - TFTP_OPTION_BLKSIZE); + result = tftp_option_add(state, &sbytes, sbytes, TFTP_OPTION_BLKSIZE); if(result == CURLE_OK) - result = tftp_option_add(state, &sbytes, - (char *)state->spacket.data + sbytes, buf); + result = tftp_option_add(state, &sbytes, sbytes, buf); /* add timeout option */ curl_msnprintf(buf, sizeof(buf), "%d", state->retry_time); if(result == CURLE_OK) - result = tftp_option_add(state, &sbytes, - (char *)state->spacket.data + sbytes, - TFTP_OPTION_INTERVAL); + result = tftp_option_add(state, &sbytes, sbytes, TFTP_OPTION_INTERVAL); if(result == CURLE_OK) - result = tftp_option_add(state, &sbytes, - (char *)state->spacket.data + sbytes, buf); + result = tftp_option_add(state, &sbytes, sbytes, buf); if(result != CURLE_OK) { failf(data, "TFTP buffer too small for options"); - free(filename); return CURLE_TFTP_ILLEGAL; } } @@ -537,7 +524,6 @@ static CURLcode tftp_send_first(struct tftp_conn *state, (SEND_TYPE_ARG3)sbytes, 0, CURL_SENDTO_ARG5(&remote_addr->curl_sa_addr), (curl_socklen_t)remote_addr->addrlen); - free(filename); if(senddata != (ssize_t)sbytes) { char buffer[STRERROR_LEN]; failf(data, "%s", curlx_strerror(SOCKERRNO, buffer, sizeof(buffer))); @@ -576,7 +562,7 @@ static CURLcode tftp_send_first(struct tftp_conn *state, /* the next blocknum is x + 1 but it needs to wrap at an unsigned 16bit boundary */ -#define NEXT_BLOCKNUM(x) (((x) + 1)&0xffff) +#define NEXT_BLOCKNUM(x) (((x) + 1) & 0xffff) /********************************************************** * @@ -790,7 +776,7 @@ static CURLcode tftp_tx(struct tftp_conn *state, tftp_event_t event) bufptr += cb; } while(state->sbytes < state->blksize && cb); - sbytes = sendto(state->sockfd, (void *) state->spacket.data, + sbytes = sendto(state->sockfd, (void *)state->spacket.data, 4 + (SEND_TYPE_ARG3)state->sbytes, SEND_4TH_ARG, (struct sockaddr *)&state->remote_addr, state->remote_addrlen); @@ -801,7 +787,7 @@ static CURLcode tftp_tx(struct tftp_conn *state, tftp_event_t event) } /* Update the progress meter */ k->writebytecount += state->sbytes; - Curl_pgrsSetUploadCounter(data, k->writebytecount); + Curl_pgrs_upload_inc(data, state->sbytes); break; case TFTP_EVENT_TIMEOUT: @@ -948,7 +934,7 @@ static void tftp_conn_dtor(void *key, size_t klen, void *entry) (void)klen; Curl_safefree(state->rpacket.data); Curl_safefree(state->spacket.data); - free(state); + curlx_free(state); } /********************************************************** @@ -969,7 +955,7 @@ static CURLcode tftp_connect(struct Curl_easy *data, bool *done) blksize = TFTP_BLKSIZE_DEFAULT; - state = calloc(1, sizeof(*state)); + state = curlx_calloc(1, sizeof(*state)); if(!state || Curl_conn_meta_set(conn, CURL_META_TFTP_CONN, state, tftp_conn_dtor)) return CURLE_OUT_OF_MEMORY; @@ -985,14 +971,14 @@ static CURLcode tftp_connect(struct Curl_easy *data, bool *done) need_blksize = TFTP_BLKSIZE_DEFAULT; if(!state->rpacket.data) { - state->rpacket.data = calloc(1, need_blksize + 2 + 2); + state->rpacket.data = curlx_calloc(1, need_blksize + 2 + 2); if(!state->rpacket.data) return CURLE_OUT_OF_MEMORY; } if(!state->spacket.data) { - state->spacket.data = calloc(1, need_blksize + 2 + 2); + state->spacket.data = curlx_calloc(1, need_blksize + 2 + 2); if(!state->spacket.data) return CURLE_OUT_OF_MEMORY; @@ -1142,15 +1128,14 @@ static CURLcode tftp_receive_packet(struct Curl_easy *data, (NEXT_BLOCKNUM(state->block) == getrpacketblock(&state->rpacket))) { result = Curl_client_write(data, CLIENTWRITE_BODY, (char *)state->rpacket.data + 4, - state->rbytes-4); + state->rbytes - 4); if(result) { tftp_state_machine(state, TFTP_EVENT_ERROR); return result; } } break; - case TFTP_EVENT_ERROR: - { + case TFTP_EVENT_ERROR: { unsigned short error = getrpacketblock(&state->rpacket); char *str = (char *)state->rpacket.data + 4; size_t strn = state->rbytes - 4; @@ -1176,9 +1161,10 @@ static CURLcode tftp_receive_packet(struct Curl_easy *data, } /* Update the progress meter */ - if(Curl_pgrsUpdate(data)) { + result = Curl_pgrsUpdate(data); + if(result) { tftp_state_machine(state, TFTP_EVENT_ERROR); - return CURLE_ABORTED_BY_CALLBACK; + return result; } } return result; @@ -1200,8 +1186,8 @@ static timediff_t tftp_state_timeout(struct tftp_conn *state, if(event) *event = TFTP_EVENT_NONE; - timeout_ms = Curl_timeleft(state->data, NULL, - (state->state == TFTP_STATE_START)); + timeout_ms = Curl_timeleft_ms(state->data, + (state->state == TFTP_STATE_START)); if(timeout_ms < 0) { state->error = TFTP_ERR_TIMEOUT; state->state = TFTP_STATE_FIN; @@ -1298,10 +1284,7 @@ static CURLcode tftp_doing(struct Curl_easy *data, bool *dophase_done) /* The multi code does not have this logic for the DOING state so we provide it for TFTP since it may do the entire transfer in this state. */ - if(Curl_pgrsUpdate(data)) - result = CURLE_ABORTED_BY_CALLBACK; - else - result = Curl_speedcheck(data, curlx_now()); + result = Curl_pgrsCheck(data); } return result; } @@ -1336,7 +1319,6 @@ static CURLcode tftp_perform(struct Curl_easy *data, bool *dophase_done) return result; } - /********************************************************** * * tftp_do diff --git a/lib/transfer.c b/lib/transfer.c index d7014aab87e5..c365d0896ddd 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -39,9 +39,7 @@ #ifdef HAVE_SYS_IOCTL_H #include #endif -#ifndef UNDER_CE #include -#endif #ifdef HAVE_SYS_PARAM_H #include @@ -58,23 +56,17 @@ #endif #include "urldata.h" -#include -#include "netrc.h" -#include "content_encoding.h" #include "hostip.h" #include "cfilters.h" #include "cw-out.h" #include "transfer.h" #include "sendf.h" -#include "speedcheck.h" +#include "curl_trc.h" #include "progress.h" #include "http.h" #include "url.h" #include "getinfo.h" -#include "vtls/vtls.h" -#include "vquic/vquic.h" -#include "select.h" #include "multiif.h" #include "connect.h" #include "http2.h" @@ -82,13 +74,10 @@ #include "hsts.h" #include "setopt.h" #include "headers.h" - -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" +#include "bufref.h" #if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \ - !defined(CURL_DISABLE_IMAP) + !defined(CURL_DISABLE_IMAP) /* * checkheaders() checks the linked list of custom headers for a * particular header (prefix). Provide the prefix without colon! @@ -101,11 +90,11 @@ char *Curl_checkheaders(const struct Curl_easy *data, { struct curl_slist *head; DEBUGASSERT(thislen); - DEBUGASSERT(thisheader[thislen-1] != ':'); + DEBUGASSERT(thisheader[thislen - 1] != ':'); for(head = data->set.headers; head; head = head->next) { if(curl_strnequal(head->data, thisheader, thislen) && - Curl_headersep(head->data[thislen]) ) + Curl_headersep(head->data[thislen])) return head->data; } @@ -117,13 +106,13 @@ static int data_pending(struct Curl_easy *data, bool rcvd_eagain) { struct connectdata *conn = data->conn; - if(conn->handler->protocol&PROTO_FAMILY_FTP) + if(conn->handler->protocol & PROTO_FAMILY_FTP) return Curl_conn_data_pending(data, SECONDARYSOCKET); /* in the case of libssh2, we can never be really sure that we have emptied its internal buffers so we MUST always try until we get EAGAIN back */ return (!rcvd_eagain && - conn->handler->protocol&(CURLPROTO_SCP|CURLPROTO_SFTP)) || + conn->handler->protocol & (CURLPROTO_SCP | CURLPROTO_SFTP)) || Curl_conn_data_pending(data, FIRSTSOCKET); } @@ -186,56 +175,46 @@ CURLcode Curl_xfer_send_shutdown(struct Curl_easy *data, bool *done) * @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 xfer_recv_resp(struct Curl_easy *data, - char *buf, size_t blen, - bool eos_reliable, - CURLcode *err) +static CURLcode xfer_recv_resp(struct Curl_easy *data, + char *buf, size_t blen, + bool eos_reliable, + size_t *pnread) { - size_t nread; + CURLcode result; DEBUGASSERT(blen > 0); + *pnread = 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; + blen = curlx_sotouz_range(data->req.size - data->req.bytecount, 0, blen); } else if(xfer_recv_shutdown_started(data)) { /* we already received everything. Do not try more. */ blen = 0; } - if(!blen) { - /* want nothing more */ - *err = CURLE_OK; - nread = 0; - } - else { - *err = Curl_xfer_recv(data, buf, blen, &nread); + if(blen) { + result = Curl_xfer_recv(data, buf, blen, pnread); + if(result) + return result; } - if(*err) - return -1; - if(nread == 0) { + if(*pnread == 0) { if(data->req.shutdown) { bool done; - *err = xfer_recv_shutdown(data, &done); - if(*err) - return -1; + result = xfer_recv_shutdown(data, &done); + if(result) + return result; if(!done) { - *err = CURLE_AGAIN; - return -1; + return CURLE_AGAIN; } } DEBUGF(infof(data, "sendrecv_dl: we are done")); } - return (ssize_t)nread; + return CURLE_OK; } /* @@ -251,9 +230,9 @@ static CURLcode sendrecv_dl(struct Curl_easy *data, char *buf, *xfer_buf; size_t blen, xfer_blen; int maxloops = 10; - curl_off_t total_received = 0; bool is_multiplex = FALSE; bool rcvd_eagain = FALSE; + bool is_eos = FALSE, rate_limited = FALSE; result = Curl_multi_xfer_buf_borrow(data, &xfer_buf, &xfer_blen); if(result) @@ -262,9 +241,7 @@ static CURLcode sendrecv_dl(struct Curl_easy *data, /* This is where we loop until we have read everything there is to read or we get a CURLE_AGAIN */ do { - bool is_eos = FALSE; size_t bytestoread; - ssize_t nread; if(!is_multiplex) { /* Multiplexed connection have inherent handling of EOF and we do not @@ -276,21 +253,27 @@ static CURLcode sendrecv_dl(struct Curl_easy *data, buf = xfer_buf; bytestoread = xfer_blen; - if(bytestoread && data->set.max_recv_speed > 0) { - /* In case of speed limit on receiving: if this loop already got - * a quarter of the quota, break out. We want to stutter a bit - * to keep in the limit, but too small receives will just cost - * cpu unnecessarily. */ - if(total_received && (total_received >= (data->set.max_recv_speed / 4))) + if(bytestoread && Curl_rlimit_active(&data->progress.dl.rlimit)) { + curl_off_t dl_avail = Curl_rlimit_avail(&data->progress.dl.rlimit, + Curl_pgrs_now(data)); + /* DEBUGF(infof(data, "dl_rlimit, available=%" FMT_OFF_T, dl_avail)); + */ + /* In case of rate limited downloads: if this loop already got + * data and less than 16k is left in the limit, break out. + * We want to stutter a bit to keep in the limit, but too small + * receives will just cost cpu unnecessarily. */ + if(dl_avail <= 0) { + rate_limited = TRUE; break; - if(data->set.max_recv_speed < (curl_off_t)bytestoread) - bytestoread = (size_t)data->set.max_recv_speed; + } + if(dl_avail < (curl_off_t)bytestoread) + bytestoread = (size_t)dl_avail; } rcvd_eagain = FALSE; - nread = xfer_recv_resp(data, buf, bytestoread, is_multiplex, &result); - if(nread < 0) { - if(CURLE_AGAIN != result) + result = xfer_recv_resp(data, buf, bytestoread, is_multiplex, &blen); + if(result) { + if(result != CURLE_AGAIN) goto out; /* real error */ rcvd_eagain = TRUE; result = CURLE_OK; @@ -298,7 +281,7 @@ static CURLcode sendrecv_dl(struct Curl_easy *data, !data->req.resp_trailer) { DEBUGF(infof(data, "EAGAIN, download done, no trailer announced, " "not waiting for EOS")); - nread = 0; + blen = 0; /* continue as if we received the EOS */ } else @@ -306,23 +289,15 @@ static CURLcode sendrecv_dl(struct Curl_easy *data, } /* We only get a 0-length receive at the end of the response */ - blen = (size_t)nread; is_eos = (blen == 0); 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(is_multiplex) - DEBUGF(infof(data, "nread == 0, stream closed, bailing")); - else - DEBUGF(infof(data, "nread <= 0, server closed connection, bailing")); result = Curl_req_stop_send_recv(data); if(result) goto out; if(k->eos_written) /* already did write this to client, leave */ break; } - total_received += blen; result = Curl_xfer_write_resp(data, buf, blen, is_eos); if(result || data->req.done) @@ -334,21 +309,21 @@ static CURLcode sendrecv_dl(struct Curl_easy *data, if((!is_multiplex && data->req.download_done) || is_eos) { data->req.keepon &= ~KEEP_RECV; } - /* if we are PAUSEd or stopped receiving, leave the loop */ - if((k->keepon & KEEP_RECV_PAUSE) || !(k->keepon & KEEP_RECV)) + /* if we stopped receiving, leave the loop */ + if(!(k->keepon & KEEP_RECV)) break; } while(maxloops--); - if(!Curl_xfer_is_blocked(data) && + if(!is_eos && !rate_limited && CURL_WANT_RECV(data) && (!rcvd_eagain || data_pending(data, rcvd_eagain))) { - /* Did not read until EAGAIN or there is still data pending + /* Did not read until EAGAIN/EOS or there is still data pending * in buffers. Mark as read-again via simulated SELECT results. */ Curl_multi_mark_dirty(data); CURL_TRC_M(data, "sendrecv_dl() no EAGAIN/pending data, mark as dirty"); } - if(((k->keepon & (KEEP_RECV|KEEP_SEND)) == KEEP_SEND) && + if(((k->keepon & (KEEP_RECV | KEEP_SEND)) == KEEP_SEND) && (conn->bits.close || is_multiplex)) { /* When we have read the entire thing and the close bit is set, the server may now close the connection. If there is now any kind of sending going @@ -383,12 +358,11 @@ static CURLcode sendrecv_ul(struct Curl_easy *data) * Curl_sendrecv() is the low-level function to be called when data is to * be read and written to/from the connection. */ -CURLcode Curl_sendrecv(struct Curl_easy *data, struct curltime *nowp) +CURLcode Curl_sendrecv(struct Curl_easy *data) { struct SingleRequest *k = &data->req; CURLcode result = CURLE_OK; - DEBUGASSERT(nowp); if(Curl_xfer_is_blocked(data)) { result = CURLE_OK; goto out; @@ -403,32 +377,31 @@ CURLcode Curl_sendrecv(struct Curl_easy *data, struct curltime *nowp) } /* If we still have writing to do, we check if we have a writable socket. */ - if(Curl_req_want_send(data) || (data->req.keepon & KEEP_SEND_TIMED)) { + if(Curl_req_want_send(data)) { result = sendrecv_ul(data); if(result) goto out; } - if(Curl_pgrsUpdate(data)) - result = CURLE_ABORTED_BY_CALLBACK; - else - result = Curl_speedcheck(data, *nowp); + result = Curl_pgrsCheck(data); if(result) goto out; if(k->keepon) { - if(0 > Curl_timeleft(data, nowp, FALSE)) { + if(Curl_timeleft_ms(data, FALSE) < 0) { if(k->size != -1) { failf(data, "Operation timed out after %" FMT_TIMEDIFF_T " milliseconds with %" FMT_OFF_T " out of %" FMT_OFF_T " bytes received", - curlx_timediff(*nowp, data->progress.t_startsingle), + curlx_ptimediff_ms(Curl_pgrs_now(data), + &data->progress.t_startsingle), k->bytecount, k->size); } else { failf(data, "Operation timed out after %" FMT_TIMEDIFF_T " milliseconds with %" FMT_OFF_T " bytes received", - curlx_timediff(*nowp, data->progress.t_startsingle), + curlx_ptimediff_ms(Curl_pgrs_now(data), + &data->progress.t_startsingle), k->bytecount); } result = CURLE_OPERATION_TIMEDOUT; @@ -447,16 +420,14 @@ CURLcode Curl_sendrecv(struct Curl_easy *data, struct curltime *nowp) result = CURLE_PARTIAL_FILE; goto out; } - if(Curl_pgrsUpdate(data)) { - result = CURLE_ABORTED_BY_CALLBACK; - goto out; - } } /* If there is nothing more to send/recv, the request is done */ - if((k->keepon & (KEEP_RECVBITS|KEEP_SENDBITS)) == 0) + if((k->keepon & (KEEP_RECV | KEEP_SEND)) == 0) data->req.done = TRUE; + result = Curl_pgrsUpdate(data); + out: if(result) DEBUGF(infof(data, "Curl_sendrecv() -> %d", result)); @@ -499,7 +470,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) is allowed to be changed by the user between transfers */ if(data->set.uh) { CURLUcode uc; - free(data->set.str[STRING_SET_URL]); + curlx_free(data->set.str[STRING_SET_URL]); uc = curl_url_get(data->set.uh, CURLUPART_URL, &data->set.str[STRING_SET_URL], 0); if(uc) { @@ -508,13 +479,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) } } - /* since the URL may have been redirected in a previous use of this handle */ - if(data->state.url_alloc) { - Curl_safefree(data->state.url); - data->state.url_alloc = FALSE; - } - - data->state.url = data->set.str[STRING_SET_URL]; + Curl_bufref_set(&data->state.url, data->set.str[STRING_SET_URL], 0, NULL); if(data->set.postfields && data->set.set_resume_from) { /* we cannot */ @@ -553,14 +518,17 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) data->state.infilesize = 0; /* If there is a list of cookie files to read, do it now! */ - Curl_cookie_loadfiles(data); + result = Curl_cookie_loadfiles(data); + if(!result) + Curl_cookie_run(data); /* activate */ /* If there is a list of host pairs to deal with */ - if(data->state.resolve) + if(!result && data->state.resolve) result = Curl_loadhostpairs(data); - /* If there is a list of hsts files to read */ - Curl_hsts_loadfiles(data); + if(!result) + /* If there is a list of hsts files to read */ + result = Curl_hsts_loadfiles(data); if(!result) { /* Allow data->set.use_port to set which port to use. This needs to be @@ -591,7 +559,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) if(data->state.wildcardmatch) { struct WildcardData *wc; if(!data->wildcard) { - data->wildcard = calloc(1, sizeof(struct WildcardData)); + data->wildcard = curlx_calloc(1, sizeof(struct WildcardData)); if(!data->wildcard) return CURLE_OUT_OF_MEMORY; } @@ -601,9 +569,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) wc->dtor(wc->ftpwc); Curl_safefree(wc->pattern); Curl_safefree(wc->path); - result = Curl_wildcard_init(wc); /* init wildcard structures */ - if(result) - return CURLE_OUT_OF_MEMORY; + Curl_wildcard_init(wc); /* init wildcard structures */ } } #endif @@ -615,8 +581,8 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) * basically anything through an HTTP proxy we cannot limit this based on * protocol. */ - if(data->set.str[STRING_USERAGENT]) { - free(data->state.aptr.uagent); + if(!result && data->set.str[STRING_USERAGENT]) { + curlx_free(data->state.aptr.uagent); data->state.aptr.uagent = curl_maprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]); if(!data->state.aptr.uagent) @@ -648,7 +614,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data) /* Returns CURLE_OK *and* sets '*url' if a request retry is wanted. - NOTE: that the *url is malloc()ed. */ + NOTE: that the *url is curlx_malloc()ed. */ CURLcode Curl_retry_request(struct Curl_easy *data, char **url) { struct connectdata *conn = data->conn; @@ -659,12 +625,13 @@ CURLcode Curl_retry_request(struct Curl_easy *data, char **url) protocol is HTTP as when uploading over HTTP we will still get a response */ if(data->state.upload && - !(conn->handler->protocol&(PROTO_FAMILY_HTTP|CURLPROTO_RTSP))) + !(conn->handler->protocol & (PROTO_FAMILY_HTTP | CURLPROTO_RTSP))) return CURLE_OK; - if((data->req.bytecount + data->req.headerbytecount == 0) && - conn->bits.reuse && - (!data->req.no_body || (conn->handler->protocol & PROTO_FAMILY_HTTP)) + if(conn->bits.reuse && + (data->req.bytecount + data->req.headerbytecount == 0) && + ((!data->req.no_body && !data->req.done) || + (conn->handler->protocol & PROTO_FAMILY_HTTP)) #ifndef CURL_DISABLE_RTSP && (data->set.rtspreq != RTSPREQ_RECEIVE) #endif @@ -678,7 +645,7 @@ CURLcode Curl_retry_request(struct Curl_easy *data, char **url) it again. Bad luck. Retry the same request on a fresh connect! */ retry = TRUE; else if(data->state.refused_stream && - (data->req.bytecount + data->req.headerbytecount == 0) ) { + (data->req.bytecount + data->req.headerbytecount == 0)) { /* This was sent on a refused stream, safe to rerun. A refused stream error can typically only happen on HTTP/2 level if the stream is safe to issue again, but the nghttp2 API can deliver the message to other @@ -698,7 +665,7 @@ CURLcode Curl_retry_request(struct Curl_easy *data, char **url) } infof(data, "Connection died, retrying a fresh connect (retry count: %d)", data->state.retrycount); - *url = strdup(data->state.url); + *url = Curl_bufref_dup(&data->state.url); if(!*url) return CURLE_OUT_OF_MEMORY; @@ -838,6 +805,7 @@ CURLcode Curl_xfer_write_resp_hd(struct Curl_easy *data, const char *hd0, size_t hdlen, bool is_eos) { if(data->conn->handler->write_resp_hd) { + DEBUGASSERT(!hd0[hdlen]); /* null terminated */ /* protocol handlers offering this function take full responsibility * for writing all received download data to the client. */ return data->conn->handler->write_resp_hd(data, hd0, hdlen, is_eos); @@ -893,8 +861,8 @@ CURLcode Curl_xfer_recv(struct Curl_easy *data, DEBUGASSERT(data->conn); DEBUGASSERT(data->set.buffer_size > 0); - if((size_t)data->set.buffer_size < blen) - blen = (size_t)data->set.buffer_size; + if(curlx_uitouz(data->set.buffer_size) < blen) + blen = curlx_uitouz(data->set.buffer_size); return Curl_conn_recv(data, data->conn->recv_idx, buf, blen, pnrcvd); } @@ -918,51 +886,31 @@ bool Curl_xfer_is_blocked(struct Curl_easy *data) bool Curl_xfer_send_is_paused(struct Curl_easy *data) { - return (data->req.keepon & KEEP_SEND_PAUSE); + return Curl_rlimit_is_blocked(&data->progress.ul.rlimit); } bool Curl_xfer_recv_is_paused(struct Curl_easy *data) { - return (data->req.keepon & KEEP_RECV_PAUSE); + return Curl_rlimit_is_blocked(&data->progress.dl.rlimit); } CURLcode Curl_xfer_pause_send(struct Curl_easy *data, bool enable) { CURLcode result = CURLE_OK; - if(enable) { - data->req.keepon |= KEEP_SEND_PAUSE; - } - else { - data->req.keepon &= ~KEEP_SEND_PAUSE; - if(Curl_creader_is_paused(data)) - result = Curl_creader_unpause(data); - } + Curl_rlimit_block(&data->progress.ul.rlimit, enable, Curl_pgrs_now(data)); + if(!enable && Curl_creader_is_paused(data)) + result = Curl_creader_unpause(data); + Curl_pgrsSendPause(data, enable); return result; } CURLcode Curl_xfer_pause_recv(struct Curl_easy *data, bool enable) { CURLcode result = CURLE_OK; - if(enable) { - data->req.keepon |= KEEP_RECV_PAUSE; - } - else { - data->req.keepon &= ~KEEP_RECV_PAUSE; - if(Curl_cwriter_is_paused(data)) - result = Curl_cwriter_unpause(data); - } + Curl_rlimit_block(&data->progress.dl.rlimit, enable, Curl_pgrs_now(data)); + if(!enable && Curl_cwriter_is_paused(data)) + result = Curl_cwriter_unpause(data); Curl_conn_ev_data_pause(data, enable); + Curl_pgrsRecvPause(data, enable); return result; } - -bool Curl_xfer_is_too_fast(struct Curl_easy *data) -{ - struct Curl_llist_node *e = Curl_llist_head(&data->state.timeoutlist); - while(e) { - struct time_node *n = Curl_node_elem(e); - e = Curl_node_next(e); - if(n->eid == EXPIRE_TOOFAST) - return TRUE; - } - return FALSE; -} diff --git a/lib/transfer.h b/lib/transfer.h index 6145efb4a5fd..78473b1f0d89 100644 --- a/lib/transfer.h +++ b/lib/transfer.h @@ -24,7 +24,8 @@ * ***************************************************************************/ -#define Curl_headersep(x) ((((x)==':') || ((x)==';'))) +#define Curl_headersep(x) ((((x) == ':') || ((x) == ';'))) + char *Curl_checkheaders(const struct Curl_easy *data, const char *thisheader, const size_t thislen); @@ -33,7 +34,7 @@ void Curl_init_CONNECT(struct Curl_easy *data); CURLcode Curl_pretransfer(struct Curl_easy *data); -CURLcode Curl_sendrecv(struct Curl_easy *data, struct curltime *nowp); +CURLcode Curl_sendrecv(struct Curl_easy *data); CURLcode Curl_retry_request(struct Curl_easy *data, char **url); bool Curl_meets_timecondition(struct Curl_easy *data, time_t timeofdoc); @@ -143,7 +144,4 @@ bool Curl_xfer_recv_is_paused(struct Curl_easy *data); CURLcode Curl_xfer_pause_send(struct Curl_easy *data, bool enable); CURLcode Curl_xfer_pause_recv(struct Curl_easy *data, bool enable); -/* Query if transfer has expire timeout TOOFAST set. */ -bool Curl_xfer_is_too_fast(struct Curl_easy *data); - #endif /* HEADER_CURL_TRANSFER_H */ diff --git a/lib/uint-bset.c b/lib/uint-bset.c index 7b822344c1f6..32aebe7cda7d 100644 --- a/lib/uint-bset.c +++ b/lib/uint-bset.c @@ -23,40 +23,36 @@ ***************************************************************************/ #include "curl_setup.h" -#include "uint-bset.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" +#include "uint-bset.h" #ifdef DEBUGBUILD -#define CURL_UINT_BSET_MAGIC 0x62757473 +#define CURL_UINT32_BSET_MAGIC 0x62757473 #endif -void Curl_uint_bset_init(struct uint_bset *bset) +void Curl_uint32_bset_init(struct uint32_bset *bset) { memset(bset, 0, sizeof(*bset)); #ifdef DEBUGBUILD - bset->init = CURL_UINT_BSET_MAGIC; + bset->init = CURL_UINT32_BSET_MAGIC; #endif } - -CURLcode Curl_uint_bset_resize(struct uint_bset *bset, unsigned int nmax) +CURLcode Curl_uint32_bset_resize(struct uint32_bset *bset, uint32_t nmax) { - unsigned int nslots = (nmax < (UINT_MAX-63)) ? - ((nmax + 63) / 64) : (UINT_MAX / 64); + uint32_t nslots = (nmax < (UINT32_MAX - 63)) ? + ((nmax + 63) / 64) : (UINT32_MAX / 64); - DEBUGASSERT(bset->init == CURL_UINT_BSET_MAGIC); + DEBUGASSERT(bset->init == CURL_UINT32_BSET_MAGIC); if(nslots != bset->nslots) { - curl_uint64_t *slots = calloc(nslots, sizeof(curl_uint64_t)); + uint64_t *slots = curlx_calloc(nslots, sizeof(uint64_t)); if(!slots) return CURLE_OUT_OF_MEMORY; if(bset->slots) { memcpy(slots, bset->slots, - (CURLMIN(nslots, bset->nslots) * sizeof(curl_uint64_t))); - free(bset->slots); + (CURLMIN(nslots, bset->nslots) * sizeof(uint64_t))); + curlx_free(bset->slots); } bset->slots = slots; bset->nslots = nslots; @@ -65,25 +61,24 @@ CURLcode Curl_uint_bset_resize(struct uint_bset *bset, unsigned int nmax) return CURLE_OK; } - -void Curl_uint_bset_destroy(struct uint_bset *bset) +void Curl_uint32_bset_destroy(struct uint32_bset *bset) { - DEBUGASSERT(bset->init == CURL_UINT_BSET_MAGIC); - free(bset->slots); + DEBUGASSERT(bset->init == CURL_UINT32_BSET_MAGIC); + curlx_free(bset->slots); memset(bset, 0, sizeof(*bset)); } #ifdef UNITTESTS -UNITTEST unsigned int Curl_uint_bset_capacity(struct uint_bset *bset) +UNITTEST uint32_t Curl_uint32_bset_capacity(struct uint32_bset *bset) { return bset->nslots * 64; } #endif -unsigned int Curl_uint_bset_count(struct uint_bset *bset) +uint32_t Curl_uint32_bset_count(struct uint32_bset *bset) { - unsigned int i; - unsigned int n = 0; + uint32_t i; + uint32_t n = 0; for(i = 0; i < bset->nslots; ++i) { if(bset->slots[i]) n += CURL_POPCOUNT64(bset->slots[i]); @@ -91,9 +86,9 @@ unsigned int Curl_uint_bset_count(struct uint_bset *bset) return n; } -bool Curl_uint_bset_empty(struct uint_bset *bset) +bool Curl_uint32_bset_empty(struct uint32_bset *bset) { - unsigned int i; + uint32_t i; for(i = bset->first_slot_used; i < bset->nslots; ++i) { if(bset->slots[i]) return FALSE; @@ -101,48 +96,43 @@ bool Curl_uint_bset_empty(struct uint_bset *bset) return TRUE; } - -void Curl_uint_bset_clear(struct uint_bset *bset) +void Curl_uint32_bset_clear(struct uint32_bset *bset) { if(bset->nslots) { - memset(bset->slots, 0, bset->nslots * sizeof(curl_uint64_t)); - bset->first_slot_used = UINT_MAX; + memset(bset->slots, 0, bset->nslots * sizeof(uint64_t)); + bset->first_slot_used = UINT32_MAX; } } - -bool Curl_uint_bset_add(struct uint_bset *bset, unsigned int i) +bool Curl_uint32_bset_add(struct uint32_bset *bset, uint32_t i) { - unsigned int islot = i / 64; + uint32_t islot = i / 64; if(islot >= bset->nslots) return FALSE; - bset->slots[islot] |= ((curl_uint64_t)1 << (i % 64)); + bset->slots[islot] |= ((uint64_t)1 << (i % 64)); if(islot < bset->first_slot_used) bset->first_slot_used = islot; return TRUE; } - -void Curl_uint_bset_remove(struct uint_bset *bset, unsigned int i) +void Curl_uint32_bset_remove(struct uint32_bset *bset, uint32_t i) { size_t islot = i / 64; if(islot < bset->nslots) - bset->slots[islot] &= ~((curl_uint64_t)1 << (i % 64)); + bset->slots[islot] &= ~((uint64_t)1 << (i % 64)); } - -bool Curl_uint_bset_contains(struct uint_bset *bset, unsigned int i) +bool Curl_uint32_bset_contains(struct uint32_bset *bset, uint32_t i) { - unsigned int islot = i / 64; + uint32_t islot = i / 64; if(islot >= bset->nslots) return FALSE; - return (bset->slots[islot] & ((curl_uint64_t)1 << (i % 64))) != 0; + return (bset->slots[islot] & ((uint64_t)1 << (i % 64))) != 0; } - -bool Curl_uint_bset_first(struct uint_bset *bset, unsigned int *pfirst) +bool Curl_uint32_bset_first(struct uint32_bset *bset, uint32_t *pfirst) { - unsigned int i; + uint32_t i; for(i = bset->first_slot_used; i < bset->nslots; ++i) { if(bset->slots[i]) { *pfirst = (i * 64) + CURL_CTZ64(bset->slots[i]); @@ -150,15 +140,15 @@ bool Curl_uint_bset_first(struct uint_bset *bset, unsigned int *pfirst) return TRUE; } } - bset->first_slot_used = *pfirst = UINT_MAX; + bset->first_slot_used = *pfirst = UINT32_MAX; return FALSE; } -bool Curl_uint_bset_next(struct uint_bset *bset, unsigned int last, - unsigned int *pnext) +bool Curl_uint32_bset_next(struct uint32_bset *bset, uint32_t last, + uint32_t *pnext) { - unsigned int islot; - curl_uint64_t x; + uint32_t islot; + uint64_t x; ++last; /* look for number one higher than last */ islot = last / 64; /* the slot this would be in */ @@ -178,42 +168,41 @@ bool Curl_uint_bset_next(struct uint_bset *bset, unsigned int last, } } } - *pnext = UINT_MAX; /* a value we cannot store */ + *pnext = UINT32_MAX; /* a value we cannot store */ return FALSE; } #ifdef CURL_POPCOUNT64_IMPLEMENT -unsigned int Curl_popcount64(curl_uint64_t x) +uint32_t Curl_popcount64(uint64_t x) { /* Compute the "Hamming Distance" between 'x' and 0, * which is the number of set bits in 'x'. * See: https://en.wikipedia.org/wiki/Hamming_weight */ - const curl_uint64_t m1 = 0x5555555555555555LL; /* 0101+ */ - const curl_uint64_t m2 = 0x3333333333333333LL; /* 00110011+ */ - const curl_uint64_t m4 = 0x0f0f0f0f0f0f0f0fLL; /* 00001111+ */ + const uint64_t m1 = 0x5555555555555555LL; /* 0101+ */ + const uint64_t m2 = 0x3333333333333333LL; /* 00110011+ */ + const uint64_t m4 = 0x0f0f0f0f0f0f0f0fLL; /* 00001111+ */ /* 1 + 256^1 + 256^2 + 256^3 + ... + 256^7 */ - const curl_uint64_t h01 = 0x0101010101010101LL; + const uint64_t h01 = 0x0101010101010101LL; x -= (x >> 1) & m1; /* replace every 2 bits with bits present */ x = (x & m2) + ((x >> 2) & m2); /* replace every nibble with bits present */ x = (x + (x >> 4)) & m4; /* replace every byte with bits present */ /* top 8 bits of x + (x<<8) + (x<<16) + (x<<24) + ... which makes the * top byte the sum of all individual 8 bytes, throw away the rest */ - return (unsigned int)((x * h01) >> 56); + return (uint32_t)((x * h01) >> 56); } #endif /* CURL_POPCOUNT64_IMPLEMENT */ - #ifdef CURL_CTZ64_IMPLEMENT -unsigned int Curl_ctz64(curl_uint64_t x) +uint32_t Curl_ctz64(uint64_t x) { - /* count trailing zeros in a curl_uint64_t. + /* count trailing zeros in a uint64_t. * divide and conquer to find the number of lower 0 bits */ - const curl_uint64_t ml32 = 0xFFFFFFFF; /* lower 32 bits */ - const curl_uint64_t ml16 = 0x0000FFFF; /* lower 16 bits */ - const curl_uint64_t ml8 = 0x000000FF; /* lower 8 bits */ - const curl_uint64_t ml4 = 0x0000000F; /* lower 4 bits */ - const curl_uint64_t ml2 = 0x00000003; /* lower 2 bits */ - unsigned int n; + const uint64_t ml32 = 0xFFFFFFFF; /* lower 32 bits */ + const uint64_t ml16 = 0x0000FFFF; /* lower 16 bits */ + const uint64_t ml8 = 0x000000FF; /* lower 8 bits */ + const uint64_t ml4 = 0x0000000F; /* lower 4 bits */ + const uint64_t ml2 = 0x00000003; /* lower 2 bits */ + uint32_t n; if(!x) return 64; @@ -238,6 +227,6 @@ unsigned int Curl_ctz64(curl_uint64_t x) n = n + 2; x = x >> 2; } - return n - (unsigned int)(x & 1); + return n - (uint32_t)(x & 1); } #endif /* CURL_CTZ64_IMPLEMENT */ diff --git a/lib/uint-bset.h b/lib/uint-bset.h index cc405cc656e3..7455c427df94 100644 --- a/lib/uint-bset.h +++ b/lib/uint-bset.h @@ -25,8 +25,6 @@ ***************************************************************************/ #include "curl_setup.h" -#include - /* A bitset for unsigned int values. * It can hold the numbers from 0 - (nmax - 1), * rounded to the next 64 multiple. @@ -39,51 +37,51 @@ * the price of slightly slower operations. */ -struct uint_bset { - curl_uint64_t *slots; - unsigned int nslots; - unsigned int first_slot_used; +struct uint32_bset { + uint64_t *slots; + uint32_t nslots; + uint32_t first_slot_used; #ifdef DEBUGBUILD int init; #endif }; /* Initialize the bitset with capacity 0. */ -void Curl_uint_bset_init(struct uint_bset *bset); +void Curl_uint32_bset_init(struct uint32_bset *bset); /* Resize the bitset capacity to hold numbers from 0 to `nmax`, * which rounds up `nmax` to the next multiple of 64. */ -CURLcode Curl_uint_bset_resize(struct uint_bset *bset, unsigned int nmax); +CURLcode Curl_uint32_bset_resize(struct uint32_bset *bset, uint32_t nmax); /* Destroy the bitset, freeing all resources. */ -void Curl_uint_bset_destroy(struct uint_bset *bset); +void Curl_uint32_bset_destroy(struct uint32_bset *bset); /* Get the bitset capacity, e.g. can hold numbers from 0 to capacity - 1. */ -unsigned int Curl_uint_bset_capacity(struct uint_bset *bset); +uint32_t Curl_uint32_bset_capacity(struct uint32_bset *bset); /* Get the cardinality of the bitset, e.g. numbers present in the set. */ -unsigned int Curl_uint_bset_count(struct uint_bset *bset); +uint32_t Curl_uint32_bset_count(struct uint32_bset *bset); /* TRUE of bitset is empty */ -bool Curl_uint_bset_empty(struct uint_bset *bset); +bool Curl_uint32_bset_empty(struct uint32_bset *bset); /* Clear the bitset, making it empty. */ -void Curl_uint_bset_clear(struct uint_bset *bset); +void Curl_uint32_bset_clear(struct uint32_bset *bset); /* Add the number `i` to the bitset. Return FALSE if the number is * outside the set's capacity. * Numbers can be added more than once, without making a difference. */ -bool Curl_uint_bset_add(struct uint_bset *bset, unsigned int i); +bool Curl_uint32_bset_add(struct uint32_bset *bset, uint32_t i); /* Remove the number `i` from the bitset. */ -void Curl_uint_bset_remove(struct uint_bset *bset, unsigned int i); +void Curl_uint32_bset_remove(struct uint32_bset *bset, uint32_t i); /* Return TRUE if the bitset contains number `i`. */ -bool Curl_uint_bset_contains(struct uint_bset *bset, unsigned int i); +bool Curl_uint32_bset_contains(struct uint32_bset *bset, uint32_t i); /* Get the first number in the bitset, e.g. the smallest. * Returns FALSE when the bitset is empty. */ -bool Curl_uint_bset_first(struct uint_bset *bset, unsigned int *pfirst); +bool Curl_uint32_bset_first(struct uint32_bset *bset, uint32_t *pfirst); /* Get the next number in the bitset, following `last` in natural order. * Put another way, this is the smallest number greater than `last` in @@ -96,20 +94,19 @@ bool Curl_uint_bset_first(struct uint_bset *bset, unsigned int *pfirst); * - added numbers lower than 'last' will not show up. * - removed numbers lower or equal to 'last' will not show up. * - removed numbers higher than 'last' will not be visited. */ -bool Curl_uint_bset_next(struct uint_bset *bset, unsigned int last, - unsigned int *pnext); - +bool Curl_uint32_bset_next(struct uint32_bset *bset, uint32_t last, + uint32_t *pnext); #ifndef CURL_POPCOUNT64 -#define CURL_POPCOUNT64(x) Curl_popcount64(x) +#define CURL_POPCOUNT64(x) Curl_popcount64(x) #define CURL_POPCOUNT64_IMPLEMENT -unsigned int Curl_popcount64(curl_uint64_t x); +uint32_t Curl_popcount64(uint64_t x); #endif /* !CURL_POPCOUNT64 */ #ifndef CURL_CTZ64 #define CURL_CTZ64(x) Curl_ctz64(x) #define CURL_CTZ64_IMPLEMENT -unsigned int Curl_ctz64(curl_uint64_t x); +uint32_t Curl_ctz64(uint64_t x); #endif /* !CURL_CTZ64 */ #endif /* HEADER_CURL_UINT_BSET_H */ diff --git a/lib/uint-hash.c b/lib/uint-hash.c index 6c665078876c..b3fd9dea196c 100644 --- a/lib/uint-hash.c +++ b/lib/uint-hash.c @@ -24,34 +24,27 @@ #include "curl_setup.h" -#include - #include "uint-hash.h" -#include "curl_memory.h" - -/* The last #include file should be: */ -#include "memdebug.h" /* random patterns for API verification */ #ifdef DEBUGBUILD -#define CURL_UINTHASHINIT 0x7117e779 +#define CURL_UINT32_HASHINIT 0x7117e779 #endif -static unsigned int uint_hash_hash(unsigned int id, unsigned int slots) +static uint32_t uint32_hash_hash(uint32_t id, uint32_t slots) { return (id % slots); } - struct uint_hash_entry { struct uint_hash_entry *next; - void *value; - unsigned int id; + void *value; + uint32_t id; }; -void Curl_uint_hash_init(struct uint_hash *h, - unsigned int slots, - Curl_uint_hash_dtor *dtor) +void Curl_uint32_hash_init(struct uint_hash *h, + uint32_t slots, + Curl_uint32_hash_dtor *dtor) { DEBUGASSERT(h); DEBUGASSERT(slots); @@ -61,16 +54,16 @@ void Curl_uint_hash_init(struct uint_hash *h, h->size = 0; h->slots = slots; #ifdef DEBUGBUILD - h->init = CURL_UINTHASHINIT; + h->init = CURL_UINT32_HASHINIT; #endif } -static struct uint_hash_entry *uint_hash_mk_entry(unsigned int id, void *value) +static struct uint_hash_entry *uint32_hash_mk_entry(uint32_t id, void *value) { struct uint_hash_entry *e; /* allocate the struct for the hash entry */ - e = malloc(sizeof(*e)); + e = curlx_malloc(sizeof(*e)); if(e) { e->id = id; e->next = NULL; @@ -79,8 +72,8 @@ static struct uint_hash_entry *uint_hash_mk_entry(unsigned int id, void *value) return e; } -static void uint_hash_entry_clear(struct uint_hash *h, - struct uint_hash_entry *e) +static void uint32_hash_entry_clear(struct uint_hash *h, + struct uint_hash_entry *e) { DEBUGASSERT(h); DEBUGASSERT(e); @@ -91,78 +84,78 @@ static void uint_hash_entry_clear(struct uint_hash *h, } } -static void uint_hash_entry_destroy(struct uint_hash *h, - struct uint_hash_entry *e) +static void uint32_hash_entry_destroy(struct uint_hash *h, + struct uint_hash_entry *e) { - uint_hash_entry_clear(h, e); - free(e); + uint32_hash_entry_clear(h, e); + curlx_free(e); } -static void uint_hash_entry_unlink(struct uint_hash *h, - struct uint_hash_entry **he_anchor, - struct uint_hash_entry *he) +static void uint32_hash_entry_unlink(struct uint_hash *h, + struct uint_hash_entry **he_anchor, + struct uint_hash_entry *he) { *he_anchor = he->next; --h->size; } -static void uint_hash_elem_link(struct uint_hash *h, - struct uint_hash_entry **he_anchor, - struct uint_hash_entry *he) +static void uint32_hash_elem_link(struct uint_hash *h, + struct uint_hash_entry **he_anchor, + struct uint_hash_entry *he) { he->next = *he_anchor; *he_anchor = he; ++h->size; } -#define CURL_UINT_HASH_SLOT(h,id) h->table[uint_hash_hash(id, h->slots)] -#define CURL_UINT_HASH_SLOT_ADDR(h,id) &CURL_UINT_HASH_SLOT(h,id) +#define CURL_UINT32_HASH_SLOT(h, id) h->table[uint32_hash_hash(id, h->slots)] +#define CURL_UINT32_HASH_SLOT_ADDR(h, id) &CURL_UINT32_HASH_SLOT(h, id) -bool Curl_uint_hash_set(struct uint_hash *h, unsigned int id, void *value) +bool Curl_uint32_hash_set(struct uint_hash *h, uint32_t id, void *value) { struct uint_hash_entry *he, **slot; DEBUGASSERT(h); DEBUGASSERT(h->slots); - DEBUGASSERT(h->init == CURL_UINTHASHINIT); + DEBUGASSERT(h->init == CURL_UINT32_HASHINIT); if(!h->table) { - h->table = calloc(h->slots, sizeof(*he)); + h->table = curlx_calloc(h->slots, sizeof(*he)); if(!h->table) return FALSE; /* OOM */ } - slot = CURL_UINT_HASH_SLOT_ADDR(h, id); + slot = CURL_UINT32_HASH_SLOT_ADDR(h, id); for(he = *slot; he; he = he->next) { if(he->id == id) { /* existing key entry, overwrite by clearing old pointer */ - uint_hash_entry_clear(h, he); + uint32_hash_entry_clear(h, he); he->value = value; return TRUE; } } - he = uint_hash_mk_entry(id, value); + he = uint32_hash_mk_entry(id, value); if(!he) return FALSE; /* OOM */ - uint_hash_elem_link(h, slot, he); + uint32_hash_elem_link(h, slot, he); return TRUE; } -bool Curl_uint_hash_remove(struct uint_hash *h, unsigned int id) +bool Curl_uint32_hash_remove(struct uint_hash *h, uint32_t id) { DEBUGASSERT(h); DEBUGASSERT(h->slots); - DEBUGASSERT(h->init == CURL_UINTHASHINIT); + DEBUGASSERT(h->init == CURL_UINT32_HASHINIT); if(h->table) { struct uint_hash_entry *he, **he_anchor; - he_anchor = CURL_UINT_HASH_SLOT_ADDR(h, id); + he_anchor = CURL_UINT32_HASH_SLOT_ADDR(h, id); while(*he_anchor) { he = *he_anchor; if(id == he->id) { - uint_hash_entry_unlink(h, he_anchor, he); - uint_hash_entry_destroy(h, he); + uint32_hash_entry_unlink(h, he_anchor, he); + uint32_hash_entry_destroy(h, he); return TRUE; } he_anchor = &he->next; @@ -171,14 +164,14 @@ bool Curl_uint_hash_remove(struct uint_hash *h, unsigned int id) return FALSE; } -void *Curl_uint_hash_get(struct uint_hash *h, unsigned int id) +void *Curl_uint32_hash_get(struct uint_hash *h, uint32_t id) { DEBUGASSERT(h); - DEBUGASSERT(h->init == CURL_UINTHASHINIT); + DEBUGASSERT(h->init == CURL_UINT32_HASHINIT); if(h->table) { struct uint_hash_entry *he; DEBUGASSERT(h->slots); - he = CURL_UINT_HASH_SLOT(h, id); + he = CURL_UINT32_HASH_SLOT(h, id); while(he) { if(id == he->id) { return he->value; @@ -194,28 +187,28 @@ static void uint_hash_clear(struct uint_hash *h) if(h && h->table) { struct uint_hash_entry *he, **he_anchor; size_t i; - DEBUGASSERT(h->init == CURL_UINTHASHINIT); + DEBUGASSERT(h->init == CURL_UINT32_HASHINIT); for(i = 0; i < h->slots; ++i) { he_anchor = &h->table[i]; while(*he_anchor) { he = *he_anchor; - uint_hash_entry_unlink(h, he_anchor, he); - uint_hash_entry_destroy(h, he); + uint32_hash_entry_unlink(h, he_anchor, he); + uint32_hash_entry_destroy(h, he); } } } } #ifdef UNITTESTS -UNITTEST void Curl_uint_hash_clear(struct uint_hash *h) +UNITTEST void Curl_uint32_hash_clear(struct uint_hash *h) { uint_hash_clear(h); } #endif -void Curl_uint_hash_destroy(struct uint_hash *h) +void Curl_uint32_hash_destroy(struct uint_hash *h) { - DEBUGASSERT(h->init == CURL_UINTHASHINIT); + DEBUGASSERT(h->init == CURL_UINT32_HASHINIT); if(h->table) { uint_hash_clear(h); Curl_safefree(h->table); @@ -224,20 +217,20 @@ void Curl_uint_hash_destroy(struct uint_hash *h) h->slots = 0; } -unsigned int Curl_uint_hash_count(struct uint_hash *h) +uint32_t Curl_uint32_hash_count(struct uint_hash *h) { - DEBUGASSERT(h->init == CURL_UINTHASHINIT); + DEBUGASSERT(h->init == CURL_UINT32_HASHINIT); return h->size; } -void Curl_uint_hash_visit(struct uint_hash *h, - Curl_uint_hash_visit_cb *cb, - void *user_data) +void Curl_uint32_hash_visit(struct uint_hash *h, + Curl_uint32_hash_visit_cb *cb, + void *user_data) { if(h && h->table && cb) { struct uint_hash_entry *he; size_t i; - DEBUGASSERT(h->init == CURL_UINTHASHINIT); + DEBUGASSERT(h->init == CURL_UINT32_HASHINIT); for(i = 0; i < h->slots; ++i) { for(he = h->table[i]; he; he = he->next) { if(!cb(he->id, he->value, user_data)) diff --git a/lib/uint-hash.h b/lib/uint-hash.h index 1b52dba4c470..e7f2ab9cbc48 100644 --- a/lib/uint-hash.h +++ b/lib/uint-hash.h @@ -26,43 +26,37 @@ #include "curl_setup.h" -#include - -#include "llist.h" - -/* A version with unsigned int as key */ -typedef void Curl_uint_hash_dtor(unsigned int id, void *value); +/* A version with uint32_t as key */ +typedef void Curl_uint32_hash_dtor(uint32_t id, void *value); struct uint_hash_entry; -/* Hash for `unsigned int` as key */ +/* Hash for `uint32_t` as key */ struct uint_hash { struct uint_hash_entry **table; - Curl_uint_hash_dtor *dtor; - unsigned int slots; - unsigned int size; + Curl_uint32_hash_dtor *dtor; + uint32_t slots; + uint32_t size; #ifdef DEBUGBUILD int init; #endif }; +void Curl_uint32_hash_init(struct uint_hash *h, + uint32_t slots, + Curl_uint32_hash_dtor *dtor); +void Curl_uint32_hash_destroy(struct uint_hash *h); +void Curl_uint32_hash_clear(struct uint_hash *h); -void Curl_uint_hash_init(struct uint_hash *h, - unsigned int slots, - Curl_uint_hash_dtor *dtor); -void Curl_uint_hash_destroy(struct uint_hash *h); -void Curl_uint_hash_clear(struct uint_hash *h); - -bool Curl_uint_hash_set(struct uint_hash *h, unsigned int id, void *value); -bool Curl_uint_hash_remove(struct uint_hash *h, unsigned int id); -void *Curl_uint_hash_get(struct uint_hash *h, unsigned int id); -unsigned int Curl_uint_hash_count(struct uint_hash *h); - +bool Curl_uint32_hash_set(struct uint_hash *h, uint32_t id, void *value); +bool Curl_uint32_hash_remove(struct uint_hash *h, uint32_t id); +void *Curl_uint32_hash_get(struct uint_hash *h, uint32_t id); +uint32_t Curl_uint32_hash_count(struct uint_hash *h); -typedef bool Curl_uint_hash_visit_cb(unsigned int id, void *value, - void *user_data); +typedef bool Curl_uint32_hash_visit_cb(uint32_t id, void *value, + void *user_data); -void Curl_uint_hash_visit(struct uint_hash *h, - Curl_uint_hash_visit_cb *cb, - void *user_data); +void Curl_uint32_hash_visit(struct uint_hash *h, + Curl_uint32_hash_visit_cb *cb, + void *user_data); #endif /* HEADER_CURL_UINT_HASH_H */ diff --git a/lib/uint-spbset.c b/lib/uint-spbset.c index 2e8e2a139e74..03e9efb4247c 100644 --- a/lib/uint-spbset.c +++ b/lib/uint-spbset.c @@ -23,41 +23,38 @@ ***************************************************************************/ #include "curl_setup.h" + #include "uint-bset.h" #include "uint-spbset.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - #ifdef DEBUGBUILD -#define CURL_UINT_SPBSET_MAGIC 0x70737362 +#define CURL_UINT32_SPBSET_MAGIC 0x70737362 #endif /* Clear the bitset, making it empty. */ -UNITTEST void Curl_uint_spbset_clear(struct uint_spbset *bset); +UNITTEST void Curl_uint32_spbset_clear(struct uint32_spbset *bset); -void Curl_uint_spbset_init(struct uint_spbset *bset) +void Curl_uint32_spbset_init(struct uint32_spbset *bset) { memset(bset, 0, sizeof(*bset)); #ifdef DEBUGBUILD - bset->init = CURL_UINT_SPBSET_MAGIC; + bset->init = CURL_UINT32_SPBSET_MAGIC; #endif } -void Curl_uint_spbset_destroy(struct uint_spbset *bset) +void Curl_uint32_spbset_destroy(struct uint32_spbset *bset) { - DEBUGASSERT(bset->init == CURL_UINT_SPBSET_MAGIC); - Curl_uint_spbset_clear(bset); + DEBUGASSERT(bset->init == CURL_UINT32_SPBSET_MAGIC); + Curl_uint32_spbset_clear(bset); } -unsigned int Curl_uint_spbset_count(struct uint_spbset *bset) +uint32_t Curl_uint32_spbset_count(struct uint32_spbset *bset) { - struct uint_spbset_chunk *chunk; - unsigned int i, n = 0; + struct uint32_spbset_chunk *chunk; + uint32_t i, n = 0; for(chunk = &bset->head; chunk; chunk = chunk->next) { - for(i = 0; i < CURL_UINT_SPBSET_CH_SLOTS; ++i) { + for(i = 0; i < CURL_UINT32_SPBSET_CH_SLOTS; ++i) { if(chunk->slots[i]) n += CURL_POPCOUNT64(chunk->slots[i]); } @@ -65,37 +62,22 @@ unsigned int Curl_uint_spbset_count(struct uint_spbset *bset) return n; } -bool Curl_uint_spbset_empty(struct uint_spbset *bset) +UNITTEST void Curl_uint32_spbset_clear(struct uint32_spbset *bset) { - struct uint_spbset_chunk *chunk; - unsigned int i; - - for(chunk = &bset->head; chunk; chunk = chunk->next) { - for(i = 0; i < CURL_UINT_SPBSET_CH_SLOTS; ++i) { - if(chunk->slots[i]) - return FALSE; - } - } - return TRUE; -} - -UNITTEST void Curl_uint_spbset_clear(struct uint_spbset *bset) -{ - struct uint_spbset_chunk *next, *chunk; + struct uint32_spbset_chunk *next, *chunk; for(chunk = bset->head.next; chunk; chunk = next) { next = chunk->next; - free(chunk); + curlx_free(chunk); } memset(&bset->head, 0, sizeof(bset->head)); } - -static struct uint_spbset_chunk * -uint_spbset_get_chunk(struct uint_spbset *bset, unsigned int i, bool grow) +static struct uint32_spbset_chunk * +uint32_spbset_get_chunk(struct uint32_spbset *bset, uint32_t i, bool grow) { - struct uint_spbset_chunk *chunk, **panchor = NULL; - unsigned int i_offset = (i & ~CURL_UINT_SPBSET_CH_MASK); + struct uint32_spbset_chunk *chunk, **panchor = NULL; + uint32_t i_offset = (i & ~CURL_UINT32_SPBSET_CH_MASK); if(!bset) return NULL; @@ -116,7 +98,7 @@ uint_spbset_get_chunk(struct uint_spbset *bset, unsigned int i, bool grow) return NULL; /* need a new one */ - chunk = calloc(1, sizeof(*chunk)); + chunk = curlx_calloc(1, sizeof(*chunk)); if(!chunk) return NULL; @@ -133,62 +115,59 @@ uint_spbset_get_chunk(struct uint_spbset *bset, unsigned int i, bool grow) return chunk; } - -bool Curl_uint_spbset_add(struct uint_spbset *bset, unsigned int i) +bool Curl_uint32_spbset_add(struct uint32_spbset *bset, uint32_t i) { - struct uint_spbset_chunk *chunk; - unsigned int i_chunk; + struct uint32_spbset_chunk *chunk; + uint32_t i_chunk; - chunk = uint_spbset_get_chunk(bset, i, TRUE); + chunk = uint32_spbset_get_chunk(bset, i, TRUE); if(!chunk) return FALSE; DEBUGASSERT(i >= chunk->offset); i_chunk = (i - chunk->offset); - DEBUGASSERT((i_chunk / 64) < CURL_UINT_SPBSET_CH_SLOTS); - chunk->slots[(i_chunk / 64)] |= ((curl_uint64_t)1 << (i_chunk % 64)); + DEBUGASSERT((i_chunk / 64) < CURL_UINT32_SPBSET_CH_SLOTS); + chunk->slots[(i_chunk / 64)] |= ((uint64_t)1 << (i_chunk % 64)); return TRUE; } - -void Curl_uint_spbset_remove(struct uint_spbset *bset, unsigned int i) +void Curl_uint32_spbset_remove(struct uint32_spbset *bset, uint32_t i) { - struct uint_spbset_chunk *chunk; - unsigned int i_chunk; + struct uint32_spbset_chunk *chunk; + uint32_t i_chunk; - chunk = uint_spbset_get_chunk(bset, i, FALSE); + chunk = uint32_spbset_get_chunk(bset, i, FALSE); if(chunk) { DEBUGASSERT(i >= chunk->offset); i_chunk = (i - chunk->offset); - DEBUGASSERT((i_chunk / 64) < CURL_UINT_SPBSET_CH_SLOTS); - chunk->slots[(i_chunk / 64)] &= ~((curl_uint64_t)1 << (i_chunk % 64)); + DEBUGASSERT((i_chunk / 64) < CURL_UINT32_SPBSET_CH_SLOTS); + chunk->slots[(i_chunk / 64)] &= ~((uint64_t)1 << (i_chunk % 64)); } } - -bool Curl_uint_spbset_contains(struct uint_spbset *bset, unsigned int i) +bool Curl_uint32_spbset_contains(struct uint32_spbset *bset, uint32_t i) { - struct uint_spbset_chunk *chunk; - unsigned int i_chunk; + struct uint32_spbset_chunk *chunk; + uint32_t i_chunk; - chunk = uint_spbset_get_chunk(bset, i, FALSE); + chunk = uint32_spbset_get_chunk(bset, i, FALSE); if(chunk) { DEBUGASSERT(i >= chunk->offset); i_chunk = (i - chunk->offset); - DEBUGASSERT((i_chunk / 64) < CURL_UINT_SPBSET_CH_SLOTS); + DEBUGASSERT((i_chunk / 64) < CURL_UINT32_SPBSET_CH_SLOTS); return (chunk->slots[i_chunk / 64] & - ((curl_uint64_t)1 << (i_chunk % 64))) != 0; + ((uint64_t)1 << (i_chunk % 64))) != 0; } return FALSE; } -bool Curl_uint_spbset_first(struct uint_spbset *bset, unsigned int *pfirst) +bool Curl_uint32_spbset_first(struct uint32_spbset *bset, uint32_t *pfirst) { - struct uint_spbset_chunk *chunk; - unsigned int i; + struct uint32_spbset_chunk *chunk; + uint32_t i; for(chunk = &bset->head; chunk; chunk = chunk->next) { - for(i = 0; i < CURL_UINT_SPBSET_CH_SLOTS; ++i) { + for(i = 0; i < CURL_UINT32_SPBSET_CH_SLOTS; ++i) { if(chunk->slots[i]) { *pfirst = chunk->offset + ((i * 64) + CURL_CTZ64(chunk->slots[i])); return TRUE; @@ -199,30 +178,28 @@ bool Curl_uint_spbset_first(struct uint_spbset *bset, unsigned int *pfirst) return FALSE; } - -static bool uint_spbset_chunk_first(struct uint_spbset_chunk *chunk, - unsigned int *pfirst) +static bool uint32_spbset_chunk_first(struct uint32_spbset_chunk *chunk, + uint32_t *pfirst) { - unsigned int i; - for(i = 0; i < CURL_UINT_SPBSET_CH_SLOTS; ++i) { + uint32_t i; + for(i = 0; i < CURL_UINT32_SPBSET_CH_SLOTS; ++i) { if(chunk->slots[i]) { *pfirst = chunk->offset + ((i * 64) + CURL_CTZ64(chunk->slots[i])); return TRUE; } } - *pfirst = UINT_MAX; /* a value we cannot store */ + *pfirst = UINT32_MAX; /* a value we cannot store */ return FALSE; } - -static bool uint_spbset_chunk_next(struct uint_spbset_chunk *chunk, - unsigned int last, - unsigned int *pnext) +static bool uint32_spbset_chunk_next(struct uint32_spbset_chunk *chunk, + uint32_t last, + uint32_t *pnext) { if(chunk->offset <= last) { - curl_uint64_t x; - unsigned int i = ((last - chunk->offset) / 64); - if(i < CURL_UINT_SPBSET_CH_SLOTS) { + uint64_t x; + uint32_t i = ((last - chunk->offset) / 64); + if(i < CURL_UINT32_SPBSET_CH_SLOTS) { x = (chunk->slots[i] >> (last % 64)); if(x) { /* more bits set, next is `last` + trailing0s of the shifted slot */ @@ -230,7 +207,7 @@ static bool uint_spbset_chunk_next(struct uint_spbset_chunk *chunk, return TRUE; } /* no more bits set in the last slot, scan forward */ - for(i = i + 1; i < CURL_UINT_SPBSET_CH_SLOTS; ++i) { + for(i = i + 1; i < CURL_UINT32_SPBSET_CH_SLOTS; ++i) { if(chunk->slots[i]) { *pnext = chunk->offset + ((i * 64) + CURL_CTZ64(chunk->slots[i])); return TRUE; @@ -238,18 +215,18 @@ static bool uint_spbset_chunk_next(struct uint_spbset_chunk *chunk, } } } - *pnext = UINT_MAX; + *pnext = UINT32_MAX; return FALSE; } -bool Curl_uint_spbset_next(struct uint_spbset *bset, unsigned int last, - unsigned int *pnext) +bool Curl_uint32_spbset_next(struct uint32_spbset *bset, uint32_t last, + uint32_t *pnext) { - struct uint_spbset_chunk *chunk; - unsigned int last_offset; + struct uint32_spbset_chunk *chunk; + uint32_t last_offset; ++last; /* look for the next higher number */ - last_offset = (last & ~CURL_UINT_SPBSET_CH_MASK); + last_offset = (last & ~CURL_UINT32_SPBSET_CH_MASK); for(chunk = &bset->head; chunk; chunk = chunk->next) { if(chunk->offset >= last_offset) { @@ -259,17 +236,17 @@ bool Curl_uint_spbset_next(struct uint_spbset *bset, unsigned int last, if(chunk && (chunk->offset == last_offset)) { /* is there a number higher than last in this chunk? */ - if(uint_spbset_chunk_next(chunk, last, pnext)) + if(uint32_spbset_chunk_next(chunk, last, pnext)) return TRUE; /* not in this chunk */ chunk = chunk->next; } /* look for the first in the "higher" chunks, if there are any. */ while(chunk) { - if(uint_spbset_chunk_first(chunk, pnext)) + if(uint32_spbset_chunk_first(chunk, pnext)) return TRUE; chunk = chunk->next; } - *pnext = UINT_MAX; + *pnext = UINT32_MAX; return FALSE; } diff --git a/lib/uint-spbset.h b/lib/uint-spbset.h index bd2347902c3b..4b105c02ed78 100644 --- a/lib/uint-spbset.h +++ b/lib/uint-spbset.h @@ -25,10 +25,8 @@ ***************************************************************************/ #include "curl_setup.h" -#include - -/* A "sparse" bitset for unsigned int values. - * It can hold any unsigned int value. +/* A "sparse" bitset for uint32_t values. + * It can hold any uint32_t value. * * Optimized for the case where only a small set of numbers need * to be kept, especially when "close" together. Then storage space @@ -36,48 +34,45 @@ */ /* 4 slots = 256 bits, keep this a 2^n value. */ -#define CURL_UINT_SPBSET_CH_SLOTS 4 -#define CURL_UINT_SPBSET_CH_MASK ((CURL_UINT_SPBSET_CH_SLOTS * 64) - 1) +#define CURL_UINT32_SPBSET_CH_SLOTS 4 +#define CURL_UINT32_SPBSET_CH_MASK ((CURL_UINT32_SPBSET_CH_SLOTS * 64) - 1) /* store the uint value from offset to - * (offset + (CURL_UINT_SPBSET_CHUNK_SLOTS * 64) - 1 */ -struct uint_spbset_chunk { - struct uint_spbset_chunk *next; - curl_uint64_t slots[CURL_UINT_SPBSET_CH_SLOTS]; - unsigned int offset; + * (offset + (CURL_UINT32_SPBSET_CHUNK_SLOTS * 64) - 1 */ +struct uint32_spbset_chunk { + struct uint32_spbset_chunk *next; + uint64_t slots[CURL_UINT32_SPBSET_CH_SLOTS]; + uint32_t offset; }; -struct uint_spbset { - struct uint_spbset_chunk head; +struct uint32_spbset { + struct uint32_spbset_chunk head; #ifdef DEBUGBUILD int init; #endif }; -void Curl_uint_spbset_init(struct uint_spbset *bset); +void Curl_uint32_spbset_init(struct uint32_spbset *bset); -void Curl_uint_spbset_destroy(struct uint_spbset *bset); +void Curl_uint32_spbset_destroy(struct uint32_spbset *bset); /* Get the cardinality of the bitset, e.g. numbers present in the set. */ -unsigned int Curl_uint_spbset_count(struct uint_spbset *bset); - -/* TRUE of bitset is empty */ -bool Curl_uint_spbset_empty(struct uint_spbset *bset); +uint32_t Curl_uint32_spbset_count(struct uint32_spbset *bset); /* Add the number `i` to the bitset. * Numbers can be added more than once, without making a difference. * Returns FALSE if allocations failed. */ -bool Curl_uint_spbset_add(struct uint_spbset *bset, unsigned int i); +bool Curl_uint32_spbset_add(struct uint32_spbset *bset, uint32_t i); /* Remove the number `i` from the bitset. */ -void Curl_uint_spbset_remove(struct uint_spbset *bset, unsigned int i); +void Curl_uint32_spbset_remove(struct uint32_spbset *bset, uint32_t i); /* Return TRUE if the bitset contains number `i`. */ -bool Curl_uint_spbset_contains(struct uint_spbset *bset, unsigned int i); +bool Curl_uint32_spbset_contains(struct uint32_spbset *bset, uint32_t i); /* Get the first number in the bitset, e.g. the smallest. * Returns FALSE when the bitset is empty. */ -bool Curl_uint_spbset_first(struct uint_spbset *bset, unsigned int *pfirst); +bool Curl_uint32_spbset_first(struct uint32_spbset *bset, uint32_t *pfirst); /* Get the next number in the bitset, following `last` in natural order. * Put another way, this is the smallest number greater than `last` in @@ -90,7 +85,7 @@ bool Curl_uint_spbset_first(struct uint_spbset *bset, unsigned int *pfirst); * - added numbers lower than 'last' will not show up. * - removed numbers lower or equal to 'last' will not show up. * - removed numbers higher than 'last' will not be visited. */ -bool Curl_uint_spbset_next(struct uint_spbset *bset, unsigned int last, - unsigned int *pnext); +bool Curl_uint32_spbset_next(struct uint32_spbset *bset, uint32_t last, + uint32_t *pnext); #endif /* HEADER_CURL_UINT_SPBSET_H */ diff --git a/lib/uint-table.c b/lib/uint-table.c index 5077363ab0f3..bbfabc9edf1a 100644 --- a/lib/uint-table.c +++ b/lib/uint-table.c @@ -23,36 +23,32 @@ ***************************************************************************/ #include "curl_setup.h" -#include "uint-table.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" +#include "uint-table.h" #ifdef DEBUGBUILD -#define CURL_UINT_TBL_MAGIC 0x62757473 +#define CURL_UINT32_TBL_MAGIC 0x62757473 #endif /* Clear the table, making it empty. */ -UNITTEST void Curl_uint_tbl_clear(struct uint_tbl *tbl); +UNITTEST void Curl_uint32_tbl_clear(struct uint32_tbl *tbl); -void Curl_uint_tbl_init(struct uint_tbl *tbl, - Curl_uint_tbl_entry_dtor *entry_dtor) +void Curl_uint32_tbl_init(struct uint32_tbl *tbl, + Curl_uint32_tbl_entry_dtor *entry_dtor) { memset(tbl, 0, sizeof(*tbl)); tbl->entry_dtor = entry_dtor; - tbl->last_key_added = UINT_MAX; + tbl->last_key_added = UINT32_MAX; #ifdef DEBUGBUILD - tbl->init = CURL_UINT_TBL_MAGIC; + tbl->init = CURL_UINT32_TBL_MAGIC; #endif } - -static void uint_tbl_clear_rows(struct uint_tbl *tbl, - unsigned int from, - unsigned int upto_excluding) +static void uint32_tbl_clear_rows(struct uint32_tbl *tbl, + uint32_t from, + uint32_t upto_excluding) { - unsigned int i, end; + uint32_t i, end; end = CURLMIN(upto_excluding, tbl->nrows); for(i = from; i < end; ++i) { @@ -65,22 +61,21 @@ static void uint_tbl_clear_rows(struct uint_tbl *tbl, } } - -CURLcode Curl_uint_tbl_resize(struct uint_tbl *tbl, unsigned int nrows) +CURLcode Curl_uint32_tbl_resize(struct uint32_tbl *tbl, uint32_t nrows) { /* we use `tbl->nrows + 1` during iteration, want that to work */ - DEBUGASSERT(tbl->init == CURL_UINT_TBL_MAGIC); + DEBUGASSERT(tbl->init == CURL_UINT32_TBL_MAGIC); if(!nrows) return CURLE_BAD_FUNCTION_ARGUMENT; if(nrows != tbl->nrows) { - void **rows = calloc(nrows, sizeof(void *)); + void **rows = curlx_calloc(nrows, sizeof(void *)); if(!rows) return CURLE_OUT_OF_MEMORY; if(tbl->rows) { memcpy(rows, tbl->rows, (CURLMIN(nrows, tbl->nrows) * sizeof(void *))); if(nrows < tbl->nrows) - uint_tbl_clear_rows(tbl, nrows, tbl->nrows); - free(tbl->rows); + uint32_tbl_clear_rows(tbl, nrows, tbl->nrows); + curlx_free(tbl->rows); } tbl->rows = rows; tbl->nrows = nrows; @@ -88,50 +83,45 @@ CURLcode Curl_uint_tbl_resize(struct uint_tbl *tbl, unsigned int nrows) return CURLE_OK; } - -void Curl_uint_tbl_destroy(struct uint_tbl *tbl) +void Curl_uint32_tbl_destroy(struct uint32_tbl *tbl) { - DEBUGASSERT(tbl->init == CURL_UINT_TBL_MAGIC); - Curl_uint_tbl_clear(tbl); - free(tbl->rows); + DEBUGASSERT(tbl->init == CURL_UINT32_TBL_MAGIC); + Curl_uint32_tbl_clear(tbl); + curlx_free(tbl->rows); memset(tbl, 0, sizeof(*tbl)); } -UNITTEST void Curl_uint_tbl_clear(struct uint_tbl *tbl) +UNITTEST void Curl_uint32_tbl_clear(struct uint32_tbl *tbl) { - DEBUGASSERT(tbl->init == CURL_UINT_TBL_MAGIC); - uint_tbl_clear_rows(tbl, 0, tbl->nrows); + DEBUGASSERT(tbl->init == CURL_UINT32_TBL_MAGIC); + uint32_tbl_clear_rows(tbl, 0, tbl->nrows); DEBUGASSERT(!tbl->nentries); - tbl->last_key_added = UINT_MAX; + tbl->last_key_added = UINT32_MAX; } - -unsigned int Curl_uint_tbl_capacity(struct uint_tbl *tbl) +uint32_t Curl_uint32_tbl_capacity(struct uint32_tbl *tbl) { return tbl->nrows; } - -unsigned int Curl_uint_tbl_count(struct uint_tbl *tbl) +uint32_t Curl_uint32_tbl_count(struct uint32_tbl *tbl) { return tbl->nentries; } - -void *Curl_uint_tbl_get(struct uint_tbl *tbl, unsigned int key) +void *Curl_uint32_tbl_get(struct uint32_tbl *tbl, uint32_t key) { return (key < tbl->nrows) ? tbl->rows[key] : NULL; } - -bool Curl_uint_tbl_add(struct uint_tbl *tbl, void *entry, unsigned int *pkey) +bool Curl_uint32_tbl_add(struct uint32_tbl *tbl, void *entry, uint32_t *pkey) { - unsigned int key, start_pos; + uint32_t key, start_pos; - DEBUGASSERT(tbl->init == CURL_UINT_TBL_MAGIC); + DEBUGASSERT(tbl->init == CURL_UINT32_TBL_MAGIC); if(!entry || !pkey) return FALSE; - *pkey = UINT_MAX; + *pkey = UINT32_MAX; if(tbl->nentries == tbl->nrows) /* full */ return FALSE; @@ -160,21 +150,18 @@ bool Curl_uint_tbl_add(struct uint_tbl *tbl, void *entry, unsigned int *pkey) return FALSE; } - -void Curl_uint_tbl_remove(struct uint_tbl *tbl, unsigned int key) +void Curl_uint32_tbl_remove(struct uint32_tbl *tbl, uint32_t key) { - uint_tbl_clear_rows(tbl, key, key + 1); + uint32_tbl_clear_rows(tbl, key, key + 1); } - -bool Curl_uint_tbl_contains(struct uint_tbl *tbl, unsigned int key) +bool Curl_uint32_tbl_contains(struct uint32_tbl *tbl, uint32_t key) { return (key < tbl->nrows) ? !!tbl->rows[key] : FALSE; } - -static bool uint_tbl_next_at(struct uint_tbl *tbl, unsigned int key, - unsigned int *pkey, void **pentry) +static bool uint32_tbl_next_at(struct uint32_tbl *tbl, uint32_t key, + uint32_t *pkey, void **pentry) { for(; key < tbl->nrows; ++key) { if(tbl->rows[key]) { @@ -183,33 +170,32 @@ static bool uint_tbl_next_at(struct uint_tbl *tbl, unsigned int key, return TRUE; } } - *pkey = UINT_MAX; /* always invalid */ + *pkey = UINT32_MAX; /* always invalid */ *pentry = NULL; return FALSE; } -bool Curl_uint_tbl_first(struct uint_tbl *tbl, - unsigned int *pkey, void **pentry) +bool Curl_uint32_tbl_first(struct uint32_tbl *tbl, + uint32_t *pkey, void **pentry) { if(!pkey || !pentry) return FALSE; - if(tbl->nentries && uint_tbl_next_at(tbl, 0, pkey, pentry)) + if(tbl->nentries && uint32_tbl_next_at(tbl, 0, pkey, pentry)) return TRUE; DEBUGASSERT(!tbl->nentries); - *pkey = UINT_MAX; /* always invalid */ + *pkey = UINT32_MAX; /* always invalid */ *pentry = NULL; return FALSE; } - -bool Curl_uint_tbl_next(struct uint_tbl *tbl, unsigned int last_key, - unsigned int *pkey, void **pentry) +bool Curl_uint32_tbl_next(struct uint32_tbl *tbl, uint32_t last_key, + uint32_t *pkey, void **pentry) { if(!pkey || !pentry) return FALSE; - if(uint_tbl_next_at(tbl, last_key + 1, pkey, pentry)) + if(uint32_tbl_next_at(tbl, last_key + 1, pkey, pentry)) return TRUE; - *pkey = UINT_MAX; /* always invalid */ + *pkey = UINT32_MAX; /* always invalid */ *pentry = NULL; return FALSE; } diff --git a/lib/uint-table.h b/lib/uint-table.h index c74ec7ad634d..3fc7e34ef436 100644 --- a/lib/uint-table.h +++ b/lib/uint-table.h @@ -25,17 +25,15 @@ ***************************************************************************/ #include "curl_setup.h" -#include - /* Destructor for a single table entry */ -typedef void Curl_uint_tbl_entry_dtor(unsigned int key, void *entry); +typedef void Curl_uint32_tbl_entry_dtor(uint32_t key, void *entry); -struct uint_tbl { +struct uint32_tbl { void **rows; /* array of void* holding entries */ - Curl_uint_tbl_entry_dtor *entry_dtor; - unsigned int nrows; /* length of `rows` array */ - unsigned int nentries; /* entries in table */ - unsigned int last_key_added; /* UINT_MAX or last key added */ + Curl_uint32_tbl_entry_dtor *entry_dtor; + uint32_t nrows; /* length of `rows` array */ + uint32_t nentries; /* entries in table */ + uint32_t last_key_added; /* UINT_MAX or last key added */ #ifdef DEBUGBUILD int init; #endif @@ -44,42 +42,42 @@ struct uint_tbl { /* Initialize the table with 0 capacity. * The optional `entry_dtor` is called when a table entry is removed, * Passing NULL means no action is taken on removal. */ -void Curl_uint_tbl_init(struct uint_tbl *tbl, - Curl_uint_tbl_entry_dtor *entry_dtor); +void Curl_uint32_tbl_init(struct uint32_tbl *tbl, + Curl_uint32_tbl_entry_dtor *entry_dtor); /* Resize the table to change capacity `nmax`. When `nmax` is reduced, * all present entries with key equal or larger to `nmax` are removed. */ -CURLcode Curl_uint_tbl_resize(struct uint_tbl *tbl, unsigned int nmax); +CURLcode Curl_uint32_tbl_resize(struct uint32_tbl *tbl, uint32_t nmax); /* Destroy the table, freeing all entries. */ -void Curl_uint_tbl_destroy(struct uint_tbl *tbl); +void Curl_uint32_tbl_destroy(struct uint32_tbl *tbl); /* Get the table capacity. */ -unsigned int Curl_uint_tbl_capacity(struct uint_tbl *tbl); +uint32_t Curl_uint32_tbl_capacity(struct uint32_tbl *tbl); /* Get the number of entries in the table. */ -unsigned int Curl_uint_tbl_count(struct uint_tbl *tbl); +uint32_t Curl_uint32_tbl_count(struct uint32_tbl *tbl); /* Get the entry for key or NULL if not present */ -void *Curl_uint_tbl_get(struct uint_tbl *tbl, unsigned int key); +void *Curl_uint32_tbl_get(struct uint32_tbl *tbl, uint32_t key); /* Add a new entry to the table and assign it a free key. * Returns FALSE if the table is full. * * Keys are assigned in a round-robin manner. * No matter the capacity, UINT_MAX is never assigned. */ -bool Curl_uint_tbl_add(struct uint_tbl *tbl, void *entry, unsigned int *pkey); +bool Curl_uint32_tbl_add(struct uint32_tbl *tbl, void *entry, uint32_t *pkey); /* Remove the entry with `key`. */ -void Curl_uint_tbl_remove(struct uint_tbl *tbl, unsigned int key); +void Curl_uint32_tbl_remove(struct uint32_tbl *tbl, uint32_t key); /* Return TRUE if the table contains an tryn with that keys. */ -bool Curl_uint_tbl_contains(struct uint_tbl *tbl, unsigned int key); +bool Curl_uint32_tbl_contains(struct uint32_tbl *tbl, uint32_t key); /* Get the first entry in the table (with the smallest `key`). * Returns FALSE if the table is empty. */ -bool Curl_uint_tbl_first(struct uint_tbl *tbl, - unsigned int *pkey, void **pentry); +bool Curl_uint32_tbl_first(struct uint32_tbl *tbl, + uint32_t *pkey, void **pentry); /* Get the next key in the table, following `last_key` in natural order. * Put another way, this is the smallest key greater than `last_key` in @@ -92,7 +90,7 @@ bool Curl_uint_tbl_first(struct uint_tbl *tbl, * - added keys lower than 'last_key' will not show up. * - removed keys lower or equal to 'last_key' will not show up. * - removed keys higher than 'last_key' will not be visited. */ -bool Curl_uint_tbl_next(struct uint_tbl *tbl, unsigned int last_key, - unsigned int *pkey, void **pentry); +bool Curl_uint32_tbl_next(struct uint32_tbl *tbl, uint32_t last_key, + uint32_t *pkey, void **pentry); #endif /* HEADER_CURL_UINT_TABLE_H */ diff --git a/lib/url.c b/lib/url.c index f0fe7d3d4135..5340f5a4c99d 100644 --- a/lib/url.c +++ b/lib/url.c @@ -66,30 +66,22 @@ #include #endif -#include - #include "doh.h" #include "urldata.h" -#include "netrc.h" #include "formdata.h" #include "mime.h" +#include "bufref.h" #include "vtls/vtls.h" #include "hostip.h" #include "transfer.h" -#include "sendf.h" +#include "curl_trc.h" #include "progress.h" #include "cookie.h" #include "strcase.h" #include "escape.h" -#include "share.h" -#include "content_encoding.h" +#include "curl_share.h" #include "http_digest.h" -#include "http_negotiate.h" -#include "select.h" #include "multiif.h" -#include "easyif.h" -#include "speedcheck.h" -#include "curlx/warnless.h" #include "getinfo.h" #include "pop3.h" #include "urlapi-int.h" @@ -98,6 +90,16 @@ #include "noproxy.h" #include "cfilters.h" #include "idn.h" +#include "http_proxy.h" +#include "conncache.h" +#include "multihandle.h" +#include "strdup.h" +#include "setopt.h" +#include "altsvc.h" +#include "curlx/dynbuf.h" +#include "headers.h" +#include "curlx/strerr.h" +#include "curlx/strparse.h" /* And now for the protocols */ #include "ftp.h" @@ -112,24 +114,10 @@ #include "imap.h" #include "url.h" #include "connect.h" -#include "http_ntlm.h" #include "curl_rtmp.h" #include "gopher.h" #include "mqtt.h" -#include "http_proxy.h" -#include "conncache.h" -#include "multihandle.h" -#include "strdup.h" -#include "setopt.h" -#include "altsvc.h" -#include "curlx/dynbuf.h" -#include "headers.h" -#include "curlx/strerr.h" -#include "curlx/strparse.h" - -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" +#include "ws.h" #ifdef USE_NGHTTP2 static void data_priority_cleanup(struct Curl_easy *data); @@ -153,16 +141,16 @@ static void data_priority_cleanup(struct Curl_easy *data); #define MAX_URL_LEN 0xffff /* -* get_protocol_family() -* -* This is used to return the protocol family for a given protocol. -* -* Parameters: -* -* 'h' [in] - struct Curl_handler pointer. -* -* Returns the family as a single bit protocol identifier. -*/ + * get_protocol_family() + * + * This is used to return the protocol family for a given protocol. + * + * Parameters: + * + * 'h' [in] - struct Curl_handler pointer. + * + * Returns the family as a single bit protocol identifier. + */ static curl_prot_t get_protocol_family(const struct Curl_handler *h) { DEBUGASSERT(h); @@ -184,16 +172,8 @@ void Curl_freeset(struct Curl_easy *data) Curl_safefree(data->set.blobs[j]); } - if(data->state.referer_alloc) { - Curl_safefree(data->state.referer); - data->state.referer_alloc = FALSE; - } - data->state.referer = NULL; - if(data->state.url_alloc) { - Curl_safefree(data->state.url); - data->state.url_alloc = FALSE; - } - data->state.url = NULL; + Curl_bufref_free(&data->state.referer); + Curl_bufref_free(&data->state.url); Curl_mime_cleanpart(&data->set.mimepost); @@ -258,7 +238,7 @@ CURLcode Curl_close(struct Curl_easy **datap) Curl_expire_clear(data); /* shut off any timers left */ if(data->state.rangestringalloc) - free(data->state.range); + curlx_free(data->state.range); /* release any resolve information this transfer kept */ Curl_async_destroy(data); @@ -279,11 +259,7 @@ CURLcode Curl_close(struct Curl_easy **datap) Curl_safefree(data->state.first_host); Curl_ssl_free_certinfo(data); - if(data->state.referer_alloc) { - Curl_safefree(data->state.referer); - data->state.referer_alloc = FALSE; - } - data->state.referer = NULL; + Curl_bufref_free(&data->state.referer); up_free(data); curlx_dyn_free(&data->state.headerb); @@ -347,7 +323,7 @@ CURLcode Curl_close(struct Curl_easy **datap) Curl_freeset(data); Curl_headers_cleanup(data); Curl_netrc_cleanup(&data->state.netrc); - free(data); + curlx_free(data); return CURLE_OK; } @@ -465,8 +441,7 @@ void Curl_init_userdefined(struct Curl_easy *data) set->conn_max_idle_ms = 118 * 1000; set->conn_max_age_ms = 24 * 3600 * 1000; set->http09_allowed = FALSE; - set->httpwant = CURL_HTTP_VERSION_NONE - ; + set->httpwant = CURL_HTTP_VERSION_NONE; #if defined(USE_HTTP2) || defined(USE_HTTP3) memset(&set->priority, 0, sizeof(set->priority)); #endif @@ -501,7 +476,7 @@ CURLcode Curl_open(struct Curl_easy **curl) struct Curl_easy *data; /* simple start-up: alloc the struct, init it with zeroes and return */ - data = calloc(1, sizeof(struct Curl_easy)); + data = curlx_calloc(1, sizeof(struct Curl_easy)); if(!data) { /* this is a serious error */ DEBUGF(curl_mfprintf(stderr, "Error: calloc of Curl_easy failed\n")); @@ -514,14 +489,16 @@ CURLcode Curl_open(struct Curl_easy **curl) data->state.recent_conn_id = -1; /* and not assigned an id yet */ data->id = -1; - data->mid = UINT_MAX; - data->master_mid = UINT_MAX; + data->mid = UINT32_MAX; + data->master_mid = UINT32_MAX; data->progress.hide = TRUE; data->state.current_speed = -1; /* init to negative == impossible */ Curl_hash_init(&data->meta_hash, 23, Curl_hash_str, curlx_str_key_compare, easy_meta_freeentry); curlx_dyn_init(&data->state.headerb, CURL_MAX_HTTP_HEADER); + Curl_bufref_init(&data->state.url); + Curl_bufref_init(&data->state.referer); Curl_req_init(&data->req); Curl_initinfo(data); #ifndef CURL_DISABLE_HTTP @@ -576,10 +553,9 @@ void Curl_conn_free(struct Curl_easy *data, struct connectdata *conn) Curl_safefree(conn->unix_domain_socket); #endif Curl_safefree(conn->destination); - Curl_uint_spbset_destroy(&conn->xfers_attached); Curl_hash_destroy(&conn->meta_hash); - free(conn); /* free all the connection oriented data */ + curlx_free(conn); /* free all the connection oriented data */ } /* @@ -597,7 +573,7 @@ static bool xfer_may_multiplex(const struct Curl_easy *data, (!conn->bits.protoconnstart || !conn->bits.close)) { if(Curl_multiplex_wanted(data->multi) && - (data->state.http_neg.allowed & (CURL_HTTP_V2x|CURL_HTTP_V3x))) + (data->state.http_neg.allowed & (CURL_HTTP_V2x | CURL_HTTP_V3x))) /* allows HTTP/2 or newer */ return TRUE; } @@ -609,9 +585,8 @@ static bool xfer_may_multiplex(const struct Curl_easy *data, } #ifndef CURL_DISABLE_PROXY -static bool -proxy_info_matches(const struct proxy_info *data, - const struct proxy_info *needle) +static bool proxy_info_matches(const struct proxy_info *data, + const struct proxy_info *needle) { if((data->proxytype == needle->proxytype) && (data->port == needle->port) && @@ -621,9 +596,8 @@ proxy_info_matches(const struct proxy_info *data, return FALSE; } -static bool -socks_proxy_info_matches(const struct proxy_info *data, - const struct proxy_info *needle) +static bool socks_proxy_info_matches(const struct proxy_info *data, + const struct proxy_info *needle) { if(!proxy_info_matches(data, needle)) return FALSE; @@ -641,8 +615,8 @@ socks_proxy_info_matches(const struct proxy_info *data, } #else /* disabled, will not get called */ -#define proxy_info_matches(x,y) FALSE -#define socks_proxy_info_matches(x,y) FALSE +#define proxy_info_matches(x, y) FALSE +#define socks_proxy_info_matches(x, y) FALSE #endif /* A connection has to have been idle for less than 'conn_max_idle_ms' @@ -655,7 +629,7 @@ static bool conn_maxage(struct Curl_easy *data, timediff_t age_ms; if(data->set.conn_max_idle_ms) { - age_ms = curlx_timediff(now, conn->lastused); + age_ms = curlx_ptimediff_ms(&now, &conn->lastused); if(age_ms > data->set.conn_max_idle_ms) { infof(data, "Too old connection (%" FMT_TIMEDIFF_T " ms idle, max idle is %" FMT_TIMEDIFF_T " ms), disconnect it", @@ -665,7 +639,7 @@ static bool conn_maxage(struct Curl_easy *data, } if(data->set.conn_max_age_ms) { - age_ms = curlx_timediff(now, conn->created); + age_ms = curlx_ptimediff_ms(&now, &conn->created); if(age_ms > data->set.conn_max_age_ms) { infof(data, "Too old connection (created %" FMT_TIMEDIFF_T @@ -682,21 +656,15 @@ static bool conn_maxage(struct Curl_easy *data, * Return TRUE iff the given connection is considered dead. */ bool Curl_conn_seems_dead(struct connectdata *conn, - struct Curl_easy *data, - struct curltime *pnow) + struct Curl_easy *data) { DEBUGASSERT(!data->conn); if(!CONN_INUSE(conn)) { /* The check for a dead socket makes sense only if the connection is not in use */ bool dead; - struct curltime now; - if(!pnow) { - now = curlx_now(); - pnow = &now; - } - if(conn_maxage(data, conn, *pnow)) { + if(conn_maxage(data, conn, *Curl_pgrs_now(data))) { /* avoid check if already too old */ dead = TRUE; } @@ -713,7 +681,6 @@ bool Curl_conn_seems_dead(struct connectdata *conn, dead = (state & CONNRESULT_DEAD); /* detach the connection again */ Curl_detach_connection(data); - } else { bool input_pending = FALSE; @@ -746,11 +713,11 @@ bool Curl_conn_seems_dead(struct connectdata *conn, } CURLcode Curl_conn_upkeep(struct Curl_easy *data, - struct connectdata *conn, - struct curltime *now) + struct connectdata *conn) { CURLcode result = CURLE_OK; - if(curlx_timediff(*now, conn->keepalive) <= data->set.upkeep_interval_ms) + if(curlx_ptimediff_ms(Curl_pgrs_now(data), &conn->keepalive) <= + data->set.upkeep_interval_ms) return result; /* briefly attach for action */ @@ -768,7 +735,7 @@ CURLcode Curl_conn_upkeep(struct Curl_easy *data, } Curl_detach_connection(data); - conn->keepalive = *now; + conn->keepalive = *Curl_pgrs_now(data); return result; } @@ -808,8 +775,8 @@ static bool url_match_connect_config(struct connectdata *conn, return FALSE; /* ip_version must match */ - if(m->data->set.ipver != CURL_IPRESOLVE_WHATEVER - && m->data->set.ipver != conn->ip_version) + if(m->data->set.ipver != CURL_IPRESOLVE_WHATEVER && + m->data->set.ipver != conn->ip_version) return FALSE; if(m->needle->localdev || m->needle->localport) { @@ -911,16 +878,16 @@ static bool url_match_multiplex_limits(struct connectdata *conn, if(CONN_INUSE(conn) && m->may_multiplex) { DEBUGASSERT(conn->bits.multiplex); /* If multiplexed, make sure we do not go over concurrency limit */ - if(CONN_ATTACHED(conn) >= + if(conn->attached_xfers >= Curl_multi_max_concurrent_streams(m->data->multi)) { infof(m->data, "client side MAX_CONCURRENT_STREAMS reached" - ", skip (%u)", CONN_ATTACHED(conn)); + ", skip (%u)", conn->attached_xfers); return FALSE; } - if(CONN_ATTACHED(conn) >= - Curl_conn_get_max_concurrent(m->data, conn, FIRSTSOCKET)) { + if(conn->attached_xfers >= + Curl_conn_get_max_concurrent(m->data, conn, FIRSTSOCKET)) { infof(m->data, "MAX_CONCURRENT_STREAMS reached, skip (%u)", - CONN_ATTACHED(conn)); + conn->attached_xfers); return FALSE; } /* When not multiplexed, we have a match here! */ @@ -956,8 +923,7 @@ static bool url_match_proxy_use(struct connectdata *conn, return FALSE; if(m->needle->bits.socksproxy && - !socks_proxy_info_matches(&m->needle->socks_proxy, - &conn->socks_proxy)) + !socks_proxy_info_matches(&m->needle->socks_proxy, &conn->socks_proxy)) return FALSE; if(m->needle->bits.httpproxy) { @@ -974,9 +940,9 @@ static bool url_match_proxy_use(struct connectdata *conn, /* match SSL config to proxy */ if(!Curl_ssl_conn_config_match(m->data, conn, TRUE)) { DEBUGF(infof(m->data, - "Connection #%" FMT_OFF_T - " has different SSL proxy parameters, cannot reuse", - conn->connection_id)); + "Connection #%" FMT_OFF_T + " has different SSL proxy parameters, cannot reuse", + conn->connection_id)); return FALSE; } /* the SSL config to the server, which may apply here is checked @@ -986,7 +952,7 @@ static bool url_match_proxy_use(struct connectdata *conn, return TRUE; } #else -#define url_match_proxy_use(c,m) ((void)c, (void)m, TRUE) +#define url_match_proxy_use(c, m) ((void)c, (void)m, TRUE) #endif #ifndef CURL_DISABLE_HTTP @@ -994,7 +960,7 @@ static bool url_match_http_multiplex(struct connectdata *conn, struct url_conn_match *m) { if(m->may_multiplex && - (m->data->state.http_neg.allowed & (CURL_HTTP_V2x|CURL_HTTP_V3x)) && + (m->data->state.http_neg.allowed & (CURL_HTTP_V2x | CURL_HTTP_V3x)) && (m->needle->handler->protocol & CURLPROTO_HTTP) && !conn->httpversion_seen) { if(m->data->set.pipewait) { @@ -1042,8 +1008,8 @@ static bool url_match_http_version(struct connectdata *conn, return TRUE; } #else -#define url_match_http_multiplex(c,m) ((void)c, (void)m, TRUE) -#define url_match_http_version(c,m) ((void)c, (void)m, TRUE) +#define url_match_http_multiplex(c, m) ((void)c, (void)m, TRUE) +#define url_match_http_version(c, m) ((void)c, (void)m, TRUE) #endif static bool url_match_proto_config(struct connectdata *conn, @@ -1096,7 +1062,7 @@ static bool url_match_destination(struct connectdata *conn, { /* Additional match requirements if talking TLS OR * not talking to an HTTP proxy OR using a tunnel through a proxy */ - if((m->needle->handler->flags&PROTOPT_SSL) + if((m->needle->handler->flags & PROTOPT_SSL) #ifndef CURL_DISABLE_PROXY || !m->needle->bits.httpproxy || m->needle->bits.tunnel_proxy #endif @@ -1121,7 +1087,7 @@ static bool url_match_destination(struct connectdata *conn, if((m->needle->bits.conn_to_host && !curl_strequal( m->needle->conn_to_host.name, conn->conn_to_host.name)) || (m->needle->bits.conn_to_port && - m->needle->conn_to_port != conn->conn_to_port)) + m->needle->conn_to_port != conn->conn_to_port)) return FALSE; /* hostname and port must match */ @@ -1212,7 +1178,7 @@ static bool url_match_auth_ntlm(struct connectdata *conn, return TRUE; } #else -#define url_match_auth_ntlm(c,m) ((void)c, (void)m, TRUE) +#define url_match_auth_ntlm(c, m) ((void)c, (void)m, TRUE) #endif static bool url_match_conn(struct connectdata *conn, void *userdata) @@ -1261,7 +1227,7 @@ static bool url_match_conn(struct connectdata *conn, void *userdata) if(!url_match_multiplex_limits(conn, m)) return FALSE; - if(!CONN_INUSE(conn) && Curl_conn_seems_dead(conn, m->data, NULL)) { + if(!CONN_INUSE(conn) && Curl_conn_seems_dead(conn, m->data)) { /* remove and disconnect. */ Curl_conn_terminate(m->data, conn, FALSE); return FALSE; @@ -1283,7 +1249,7 @@ static bool url_match_result(bool result, void *userdata) return TRUE; } else if(match->seen_single_use_conn && !match->seen_multiplex_conn) { - /* We've seen a single-use, existing connection to the destination and + /* We have seen a single-use, existing connection to the destination and * no multiplexed one. It seems safe to assume that the server does * not support multiplexing. */ match->wait_pipe = FALSE; @@ -1308,12 +1274,11 @@ static bool url_match_result(bool result, void *userdata) * * The force_reuse flag is set if the connection must be used. */ -static bool -ConnectionExists(struct Curl_easy *data, - struct connectdata *needle, - struct connectdata **usethis, - bool *force_reuse, - bool *waitpipe) +static bool ConnectionExists(struct Curl_easy *data, + struct connectdata *needle, + struct connectdata **usethis, + bool *force_reuse, + bool *waitpipe) { struct url_conn_match match; bool result; @@ -1352,7 +1317,7 @@ ConnectionExists(struct Curl_easy *data, */ static struct connectdata *allocate_conn(struct Curl_easy *data) { - struct connectdata *conn = calloc(1, sizeof(struct connectdata)); + struct connectdata *conn = curlx_calloc(1, sizeof(struct connectdata)); if(!conn) return NULL; @@ -1363,15 +1328,11 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) conn->recv_idx = 0; /* default for receiving transfer data */ conn->send_idx = 0; /* default for sending transfer data */ conn->connection_id = -1; /* no ID */ + conn->attached_xfers = 0; conn->remote_port = -1; /* unknown at this point */ - /* Default protocol-independent behavior does not support persistent - connections, so we set this to force-close. Protocols that support - this need to set this to FALSE in their "curl_do" functions. */ - connclose(conn, "Default to force-close"); - /* Store creation time to help future close decision making */ - conn->created = curlx_now(); + conn->created = *Curl_pgrs_now(data); /* Store current time to give a baseline to keepalive connection times. */ conn->keepalive = conn->created; @@ -1407,12 +1368,9 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) conn->connect_only = data->set.connect_only; conn->transport_wanted = TRNSPRT_TCP; /* most of them are TCP streams */ - /* Initialize the attached xfers bitset */ - Curl_uint_spbset_init(&conn->xfers_attached); - /* Store the local bind parameters that will be used for this connection */ if(data->set.str[STRING_DEVICE]) { - conn->localdev = strdup(data->set.str[STRING_DEVICE]); + conn->localdev = curlx_strdup(data->set.str[STRING_DEVICE]); if(!conn->localdev) goto error; } @@ -1429,11 +1387,12 @@ static struct connectdata *allocate_conn(struct Curl_easy *data) #ifdef HAVE_GSSAPI conn->gssapi_delegation = data->set.gssapi_delegation; #endif + DEBUGF(infof(data, "alloc connection, bits.close=%d", conn->bits.close)); return conn; error: - free(conn->localdev); - free(conn); + curlx_free(conn->localdev); + curlx_free(conn); return NULL; } @@ -1568,7 +1527,7 @@ const struct Curl_handler *Curl_getn_scheme_handler(const char *scheme, #else NULL, #endif -#if defined(USE_SSH) +#ifdef USE_SSH &Curl_handler_scp, #else NULL, @@ -1685,12 +1644,11 @@ static CURLcode findprotocol(struct Curl_easy *data, create_conn() function when the connectdata struct is allocated. */ failf(data, "Protocol \"%s\" %s%s", protostr, p ? "disabled" : "not supported", - data->state.this_is_a_follow ? " (in redirect)":""); + data->state.this_is_a_follow ? " (in redirect)" : ""); return CURLE_UNSUPPORTED_PROTOCOL; } - CURLcode Curl_uc_to_curlcode(CURLUcode uc) { switch(uc) { @@ -1752,11 +1710,11 @@ static void zonefrom_url(CURLU *uh, struct Curl_easy *data, } #endif /* HAVE_IF_NAMETOINDEX || _WIN32 */ - free(zoneid); + curlx_free(zoneid); } } #else -#define zonefrom_url(a,b,c) Curl_nop_stmt +#define zonefrom_url(a, b, c) Curl_nop_stmt #endif /* @@ -1785,22 +1743,19 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, return CURLE_OUT_OF_MEMORY; if(data->set.str[STRING_DEFAULT_PROTOCOL] && - !Curl_is_absolute_url(data->state.url, NULL, 0, TRUE)) { + !Curl_is_absolute_url(Curl_bufref_ptr(&data->state.url), NULL, 0, TRUE)) { char *url = curl_maprintf("%s://%s", data->set.str[STRING_DEFAULT_PROTOCOL], - data->state.url); + Curl_bufref_ptr(&data->state.url)); if(!url) return CURLE_OUT_OF_MEMORY; - if(data->state.url_alloc) - free(data->state.url); - data->state.url = url; - data->state.url_alloc = TRUE; + Curl_bufref_set(&data->state.url, url, 0, curl_free); } if(!use_set_uh) { char *newurl; - uc = curl_url_set(uh, CURLUPART_URL, data->state.url, (unsigned int) - (CURLU_GUESS_SCHEME | + uc = curl_url_set(uh, CURLUPART_URL, Curl_bufref_ptr(&data->state.url), + (unsigned int)(CURLU_GUESS_SCHEME | CURLU_NON_SUPPORT_SCHEME | (data->set.disallow_username_in_url ? CURLU_DISALLOW_USER : 0) | @@ -1814,10 +1769,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, uc = curl_url_get(uh, CURLUPART_URL, &newurl, 0); if(uc) return Curl_uc_to_curlcode(uc); - if(data->state.url_alloc) - free(data->state.url); - data->state.url = newurl; - data->state.url_alloc = TRUE; + Curl_bufref_set(&data->state.url, newurl, 0, curl_free); } uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0); @@ -1849,7 +1801,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, } /* make sure the connect struct gets its own copy of the hostname */ - conn->host.rawalloc = strdup(hostname ? hostname : ""); + conn->host.rawalloc = curlx_strdup(hostname ? hostname : ""); if(!conn->host.rawalloc) return CURLE_OUT_OF_MEMORY; conn->host.name = conn->host.rawalloc; @@ -1871,21 +1823,18 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, uc = curl_url_set(uh, CURLUPART_SCHEME, "https", 0); if(uc) return Curl_uc_to_curlcode(uc); - if(data->state.url_alloc) - Curl_safefree(data->state.url); + Curl_bufref_free(&data->state.url); /* after update, get the updated version */ uc = curl_url_get(uh, CURLUPART_URL, &url, 0); if(uc) return Curl_uc_to_curlcode(uc); uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0); if(uc) { - free(url); + curlx_free(url); return Curl_uc_to_curlcode(uc); } - data->state.url = url; - data->state.url_alloc = TRUE; - infof(data, "Switched from HTTP to HTTPS due to HSTS => %s", - data->state.url); + Curl_bufref_set(&data->state.url, url, 0, curl_free); + infof(data, "Switched from HTTP to HTTPS due to HSTS => %s", url); } } #endif @@ -1942,22 +1891,22 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, uc = curl_url_get(uh, CURLUPART_OPTIONS, &data->state.up.options, CURLU_URLDECODE); if(!uc) { - conn->options = strdup(data->state.up.options); + conn->options = curlx_strdup(data->state.up.options); if(!conn->options) return CURLE_OUT_OF_MEMORY; } else if(uc != CURLUE_NO_OPTIONS) return Curl_uc_to_curlcode(uc); - uc = curl_url_get(uh, CURLUPART_PATH, &data->state.up.path, - CURLU_URLENCODE); + uc = curl_url_get(uh, CURLUPART_PATH, &data->state.up.path, CURLU_URLENCODE); if(uc) return Curl_uc_to_curlcode(uc); uc = curl_url_get(uh, CURLUPART_PORT, &data->state.up.port, CURLU_DEFAULT_PORT); if(uc) { - if(!curl_strequal("file", data->state.up.scheme)) + if((uc == CURLUE_OUT_OF_MEMORY) || + !curl_strequal("file", data->state.up.scheme)) return CURLE_OUT_OF_MEMORY; } else { @@ -1974,7 +1923,9 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, conn->remote_port = (unsigned short)port; } - (void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0); + uc = curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0); + if(uc && (uc != CURLUE_NO_QUERY)) + return CURLE_OUT_OF_MEMORY; #ifdef USE_IPV6 if(data->set.scope_id) @@ -1985,7 +1936,6 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, return CURLE_OK; } - /* * If we are doing a resumed transfer, we need to setup our stuff * properly. @@ -1996,12 +1946,12 @@ static CURLcode setup_range(struct Curl_easy *data) s->resume_from = data->set.set_resume_from; if(s->resume_from || data->set.str[STRING_SET_RANGE]) { if(s->rangestringalloc) - free(s->range); + curlx_free(s->range); if(s->resume_from) s->range = curl_maprintf("%" FMT_OFF_T "-", s->resume_from); else - s->range = strdup(data->set.str[STRING_SET_RANGE]); + s->range = curlx_strdup(data->set.str[STRING_SET_RANGE]); if(!s->range) return CURLE_OUT_OF_MEMORY; @@ -2017,7 +1967,6 @@ static CURLcode setup_range(struct Curl_easy *data) return CURLE_OK; } - /* * setup_connection_internals() - * @@ -2034,11 +1983,13 @@ static CURLcode setup_connection_internals(struct Curl_easy *data, int port; CURLcode result; + DEBUGF(infof(data, "setup connection, bits.close=%d", conn->bits.close)); if(conn->handler->setup_connection) { result = conn->handler->setup_connection(data, conn); if(result) return result; } + DEBUGF(infof(data, "setup connection, bits.close=%d", conn->bits.close)); /* Now create the destination name */ #ifndef CURL_DISABLE_PROXY @@ -2071,15 +2022,14 @@ static CURLcode setup_connection_internals(struct Curl_easy *data, return CURLE_OK; } - #ifndef CURL_DISABLE_PROXY #ifndef CURL_DISABLE_HTTP /**************************************************************** -* Detect what (if any) proxy to use. Remember that this selects a host -* name and is not limited to HTTP proxies only. -* The returned pointer must be freed by the caller (unless NULL) -****************************************************************/ + * Detect what (if any) proxy to use. Remember that this selects a host + * name and is not limited to HTTP proxies only. + * The returned pointer must be freed by the caller (unless NULL) + ****************************************************************/ static char *detect_proxy(struct Curl_easy *data, struct connectdata *conn) { @@ -2172,7 +2122,6 @@ static CURLcode parse_proxy(struct Curl_easy *data, long proxytype) { char *portptr = NULL; - int port = -1; char *proxyuser = NULL; char *proxypasswd = NULL; char *host = NULL; @@ -2187,7 +2136,6 @@ static CURLcode parse_proxy(struct Curl_easy *data, bool is_unix_proxy = FALSE; #endif - if(!uhp) { result = CURLE_OUT_OF_MEMORY; goto error; @@ -2196,7 +2144,7 @@ static CURLcode parse_proxy(struct Curl_easy *data, /* When parsing the proxy, allowing non-supported schemes since we have these made up ones for proxies. Guess scheme for URLs without it. */ uc = curl_url_set(uhp, CURLUPART_URL, proxy, - CURLU_NON_SUPPORT_SCHEME|CURLU_GUESS_SCHEME); + CURLU_NON_SUPPORT_SCHEME | CURLU_GUESS_SCHEME); if(!uc) { /* parsed okay as a URL */ uc = curl_url_get(uhp, CURLUPART_SCHEME, &scheme, 0); @@ -2257,14 +2205,18 @@ static CURLcode parse_proxy(struct Curl_easy *data, /* Is there a username and password given in this proxy url? */ uc = curl_url_get(uhp, CURLUPART_USER, &proxyuser, CURLU_URLDECODE); - if(uc && (uc != CURLUE_NO_USER)) + if(uc && (uc != CURLUE_NO_USER)) { + result = Curl_uc_to_curlcode(uc); goto error; + } uc = curl_url_get(uhp, CURLUPART_PASSWORD, &proxypasswd, CURLU_URLDECODE); - if(uc && (uc != CURLUE_NO_PASSWORD)) + if(uc && (uc != CURLUE_NO_PASSWORD)) { + result = Curl_uc_to_curlcode(uc); goto error; + } if(proxyuser || proxypasswd) { - free(proxyinfo->user); + curlx_free(proxyinfo->user); proxyinfo->user = proxyuser; result = Curl_setstropt(&data->state.aptr.proxyuser, proxyuser); proxyuser = NULL; @@ -2272,7 +2224,7 @@ static CURLcode parse_proxy(struct Curl_easy *data, goto error; Curl_safefree(proxyinfo->passwd); if(!proxypasswd) { - proxypasswd = strdup(""); + proxypasswd = curlx_strdup(""); if(!proxypasswd) { result = CURLE_OUT_OF_MEMORY; goto error; @@ -2286,29 +2238,32 @@ static CURLcode parse_proxy(struct Curl_easy *data, conn->bits.proxy_user_passwd = TRUE; /* enable it */ } - (void)curl_url_get(uhp, CURLUPART_PORT, &portptr, 0); + uc = curl_url_get(uhp, CURLUPART_PORT, &portptr, 0); + if(uc == CURLUE_OUT_OF_MEMORY) { + result = CURLE_OUT_OF_MEMORY; + goto error; + } if(portptr) { curl_off_t num; const char *p = portptr; - if(!curlx_str_number(&p, &num, 0xffff)) - port = (int)num; - free(portptr); + if(!curlx_str_number(&p, &num, UINT16_MAX)) + proxyinfo->port = (uint16_t)num; + /* Should we not error out when the port number is invalid? */ + curlx_free(portptr); } else { if(data->set.proxyport) /* None given in the proxy string, then get the default one if it is given */ - port = (int)data->set.proxyport; + proxyinfo->port = data->set.proxyport; else { if(IS_HTTPS_PROXY(proxytype)) - port = CURL_DEFAULT_HTTPS_PROXY_PORT; + proxyinfo->port = CURL_DEFAULT_HTTPS_PROXY_PORT; else - port = CURL_DEFAULT_PROXY_PORT; + proxyinfo->port = CURL_DEFAULT_PROXY_PORT; } } - if(port >= 0) - proxyinfo->port = port; /* now, clone the proxy hostname */ uc = curl_url_get(uhp, CURLUPART_HOST, &host, CURLU_URLDECODE); @@ -2326,13 +2281,13 @@ static CURLcode parse_proxy(struct Curl_easy *data, /* path will be "/", if no path was found */ if(strcmp("/", path)) { is_unix_proxy = TRUE; - free(host); - host = curl_maprintf(UNIX_SOCKET_PREFIX"%s", path); + curlx_free(host); + host = curl_maprintf(UNIX_SOCKET_PREFIX "%s", path); if(!host) { result = CURLE_OUT_OF_MEMORY; goto error; } - free(proxyinfo->host.rawalloc); + curlx_free(proxyinfo->host.rawalloc); proxyinfo->host.rawalloc = host; proxyinfo->host.name = host; host = NULL; @@ -2341,12 +2296,12 @@ static CURLcode parse_proxy(struct Curl_easy *data, if(!is_unix_proxy) { #endif - free(proxyinfo->host.rawalloc); + curlx_free(proxyinfo->host.rawalloc); proxyinfo->host.rawalloc = host; if(host[0] == '[') { /* this is a numerical IPv6, strip off the brackets */ size_t len = strlen(host); - host[len-1] = 0; /* clear the trailing bracket */ + host[len - 1] = 0; /* clear the trailing bracket */ host++; zonefrom_url(uhp, data, conn); } @@ -2357,12 +2312,12 @@ static CURLcode parse_proxy(struct Curl_easy *data, #endif error: - free(proxyuser); - free(proxypasswd); - free(host); - free(scheme); + curlx_free(proxyuser); + curlx_free(proxypasswd); + curlx_free(host); + curlx_free(scheme); #ifdef USE_UNIX_SOCKETS - free(path); + curlx_free(path); #endif curl_url_cleanup(uhp); return result; @@ -2380,9 +2335,9 @@ static CURLcode parse_proxy_auth(struct Curl_easy *data, data->state.aptr.proxypasswd : ""; CURLcode result = CURLE_OUT_OF_MEMORY; - conn->http_proxy.user = strdup(proxyuser); + conn->http_proxy.user = curlx_strdup(proxyuser); if(conn->http_proxy.user) { - conn->http_proxy.passwd = strdup(proxypasswd); + conn->http_proxy.passwd = curlx_strdup(proxypasswd); if(conn->http_proxy.passwd) result = CURLE_OK; else @@ -2414,7 +2369,7 @@ static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data, * Detect what (if any) proxy to use *************************************************************/ if(data->set.str[STRING_PROXY]) { - proxy = strdup(data->set.str[STRING_PROXY]); + proxy = curlx_strdup(data->set.str[STRING_PROXY]); /* if global proxy is set, this is it */ if(!proxy) { failf(data, "memory shortage"); @@ -2424,7 +2379,7 @@ static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data, } if(data->set.str[STRING_PRE_PROXY]) { - socksproxy = strdup(data->set.str[STRING_PRE_PROXY]); + socksproxy = curlx_strdup(data->set.str[STRING_PRE_PROXY]); /* if global socks proxy is set, this is it */ if(!socksproxy) { failf(data, "memory shortage"); @@ -2460,20 +2415,21 @@ static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data, #ifdef USE_UNIX_SOCKETS /* For the time being do not mix proxy and Unix domain sockets. See #1274 */ if(proxy && conn->unix_domain_socket) { - free(proxy); + curlx_free(proxy); proxy = NULL; } #endif if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) { - free(proxy); /* Do not bother with an empty proxy string or if the - protocol does not work with network */ + curlx_free(proxy); /* Do not bother with an empty proxy string + or if the protocol does not work with network */ proxy = NULL; } if(socksproxy && (!*socksproxy || (conn->handler->flags & PROTOPT_NONETWORK))) { - free(socksproxy); /* Do not bother with an empty socks proxy string or if - the protocol does not work with network */ + curlx_free(socksproxy); /* Do not bother with an empty socks proxy string + or if the protocol does not work with + network */ socksproxy = NULL; } @@ -2528,7 +2484,7 @@ static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data, if(!conn->socks_proxy.user) { conn->socks_proxy.user = conn->http_proxy.user; conn->http_proxy.user = NULL; - free(conn->socks_proxy.passwd); + curlx_free(conn->socks_proxy.passwd); conn->socks_proxy.passwd = conn->http_proxy.passwd; conn->http_proxy.passwd = NULL; } @@ -2558,8 +2514,8 @@ static CURLcode create_conn_helper_init_proxy(struct Curl_easy *data, out: - free(socksproxy); - free(proxy); + curlx_free(socksproxy); + curlx_free(proxy); return result; } #endif /* CURL_DISABLE_PROXY */ @@ -2653,8 +2609,8 @@ CURLcode Curl_parse_login_details(const char *login, const size_t len, *passwdp = pbuf; return CURLE_OK; error: - free(ubuf); - free(pbuf); + curlx_free(ubuf); + curlx_free(pbuf); return CURLE_OUT_OF_MEMORY; } @@ -2712,8 +2668,8 @@ static CURLcode override_login(struct Curl_easy *data, char **optionsp = &conn->options; if(data->set.str[STRING_OPTIONS]) { - free(*optionsp); - *optionsp = strdup(data->set.str[STRING_OPTIONS]); + curlx_free(*optionsp); + *optionsp = curlx_strdup(data->set.str[STRING_OPTIONS]); if(!*optionsp) return CURLE_OUT_OF_MEMORY; } @@ -2741,7 +2697,7 @@ static CURLcode override_login(struct Curl_easy *data, data->set.str[STRING_NETRC_FILE]); if(ret && ((ret == NETRC_NO_MATCH) || (data->set.use_netrc == CURL_NETRC_OPTIONAL))) { - infof(data, "Couldn't find host %s in the %s file; using defaults", + infof(data, "Could not find host %s in the %s file; using defaults", conn->host.name, (data->set.str[STRING_NETRC_FILE] ? data->set.str[STRING_NETRC_FILE] : ".netrc")); @@ -2752,8 +2708,8 @@ static CURLcode override_login(struct Curl_easy *data, return CURLE_READ_ERROR; } else { - if(!(conn->handler->flags&PROTOPT_USERPWDCTRL)) { - /* if the protocol can't handle control codes in credentials, make + if(!(conn->handler->flags & PROTOPT_USERPWDCTRL)) { + /* if the protocol cannot handle control codes in credentials, make sure there are none */ if(str_has_ctrl(*userp) || str_has_ctrl(*passwdp)) { failf(data, "control code detected in .netrc credentials"); @@ -2767,14 +2723,14 @@ static CURLcode override_login(struct Curl_easy *data, } } if(url_provided) { - free(conn->user); - conn->user = strdup(*userp); + curlx_free(conn->user); + conn->user = curlx_strdup(*userp); if(!conn->user) return CURLE_OUT_OF_MEMORY; } /* no user was set but a password, set a blank user */ if(!*userp && *passwdp) { - *userp = strdup(""); + *userp = curlx_strdup(""); if(!*userp) return CURLE_OUT_OF_MEMORY; } @@ -2798,7 +2754,7 @@ static CURLcode override_login(struct Curl_easy *data, if(uc) return Curl_uc_to_curlcode(uc); if(!*userp) { - *userp = strdup(data->state.aptr.user); + *userp = curlx_strdup(data->state.aptr.user); if(!*userp) return CURLE_OUT_OF_MEMORY; } @@ -2815,7 +2771,7 @@ static CURLcode override_login(struct Curl_easy *data, if(uc) return Curl_uc_to_curlcode(uc); if(!*passwdp) { - *passwdp = strdup(data->state.aptr.passwd); + *passwdp = curlx_strdup(data->state.aptr.passwd); if(!*passwdp) return CURLE_OUT_OF_MEMORY; } @@ -2843,14 +2799,14 @@ static CURLcode set_login(struct Curl_easy *data, } /* Store the default user */ if(!conn->user) { - conn->user = strdup(setuser); + conn->user = curlx_strdup(setuser); if(!conn->user) return CURLE_OUT_OF_MEMORY; } /* Store the default password */ if(!conn->passwd) { - conn->passwd = strdup(setpasswd); + conn->passwd = curlx_strdup(setpasswd); if(!conn->passwd) result = CURLE_OUT_OF_MEMORY; } @@ -2885,7 +2841,7 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data, if(!host || !*host) return CURLE_OK; - host_dup = strdup(host); + host_dup = curlx_strdup(host); if(!host_dup) return CURLE_OUT_OF_MEMORY; @@ -2947,7 +2903,7 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data, /* now, clone the cleaned hostname */ DEBUGASSERT(hostptr); - *hostname_result = strdup(hostptr); + *hostname_result = curlx_strdup(hostptr); if(!*hostname_result) { result = CURLE_OUT_OF_MEMORY; goto error; @@ -2956,7 +2912,7 @@ static CURLcode parse_connect_to_host_port(struct Curl_easy *data, *port_result = port; error: - free(host_dup); + curlx_free(host_dup); return result; } @@ -2995,7 +2951,7 @@ static CURLcode parse_connect_to_string(struct Curl_easy *data, hostname_to_match_len = strlen(hostname_to_match); host_match = curl_strnequal(ptr, hostname_to_match, hostname_to_match_len); - free(hostname_to_match); + curlx_free(hostname_to_match); ptr += hostname_to_match_len; host_match = host_match && *ptr == ':'; @@ -3090,6 +3046,7 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data, struct altsvc *as = NULL; int allowed_alpns = ALPN_none; struct http_negotiation *neg = &data->state.http_neg; + bool same_dest = FALSE; DEBUGF(infof(data, "Alt-svc check wanted=%x, allowed=%x", neg->wanted, neg->allowed)); @@ -3113,7 +3070,7 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data, hit = Curl_altsvc_lookup(data->asi, ALPN_h3, host, conn->remote_port, /* from */ &as /* to */, - allowed_alpns); + allowed_alpns, &same_dest); } #endif #ifdef USE_HTTP2 @@ -3123,7 +3080,7 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data, hit = Curl_altsvc_lookup(data->asi, ALPN_h2, host, conn->remote_port, /* from */ &as /* to */, - allowed_alpns); + allowed_alpns, &same_dest); } #endif if(!hit && (neg->wanted & CURL_HTTP_V1x) && @@ -3132,11 +3089,30 @@ static CURLcode parse_connect_to_slist(struct Curl_easy *data, hit = Curl_altsvc_lookup(data->asi, ALPN_h1, host, conn->remote_port, /* from */ &as /* to */, - allowed_alpns); + allowed_alpns, &same_dest); } - if(hit) { - char *hostd = strdup((char *)as->dst.host); + if(hit && same_dest) { + /* same destination, but more HTTPS version options */ + switch(as->dst.alpnid) { + case ALPN_h1: + neg->wanted |= CURL_HTTP_V1x; + neg->preferred = CURL_HTTP_V1x; + break; + case ALPN_h2: + neg->wanted |= CURL_HTTP_V2x; + neg->preferred = CURL_HTTP_V2x; + break; + case ALPN_h3: + neg->wanted |= CURL_HTTP_V3x; + neg->preferred = CURL_HTTP_V3x; + break; + default: /* should not be possible */ + break; + } + } + else if(hit) { + char *hostd = curlx_strdup((char *)as->dst.host); if(!hostd) return CURLE_OUT_OF_MEMORY; conn->conn_to_host.rawalloc = hostd; @@ -3188,7 +3164,7 @@ static CURLcode resolve_unix(struct Curl_easy *data, /* Unix domain sockets are local. The host gets ignored, just use the * specified domain socket address. Do not cache "DNS entries". There is * no DNS involved and we already have the file system path available. */ - hostaddr = calloc(1, sizeof(struct Curl_dns_entry)); + hostaddr = curlx_calloc(1, sizeof(struct Curl_dns_entry)); if(!hostaddr) return CURLE_OUT_OF_MEMORY; @@ -3198,7 +3174,7 @@ static CURLcode resolve_unix(struct Curl_easy *data, if(longpath) /* Long paths are not supported for now */ failf(data, "Unix socket path too long: '%s'", unix_path); - free(hostaddr); + curlx_free(hostaddr); return longpath ? CURLE_COULDNT_RESOLVE_HOST : CURLE_OUT_OF_MEMORY; } @@ -3218,7 +3194,7 @@ static CURLcode resolve_server(struct Curl_easy *data, { struct hostname *ehost; int eport; - timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE); + timediff_t timeout_ms = Curl_timeleft_ms(data, TRUE); const char *peertype = "host"; CURLcode result; @@ -3230,7 +3206,7 @@ static CURLcode resolve_server(struct Curl_easy *data, #ifndef CURL_DISABLE_PROXY if(!unix_path && CONN_IS_PROXIED(conn) && conn->socks_proxy.host.name && - !strncmp(UNIX_SOCKET_PREFIX"/", + !strncmp(UNIX_SOCKET_PREFIX "/", conn->socks_proxy.host.name, sizeof(UNIX_SOCKET_PREFIX))) unix_path = conn->socks_proxy.host.name + sizeof(UNIX_SOCKET_PREFIX) - 1; #endif @@ -3261,7 +3237,7 @@ static CURLcode resolve_server(struct Curl_easy *data, } /* Resolve target host right on */ - conn->hostname_resolve = strdup(ehost->name); + conn->hostname_resolve = curlx_strdup(ehost->name); if(!conn->hostname_resolve) return CURLE_OUT_OF_MEMORY; @@ -3276,7 +3252,8 @@ static CURLcode resolve_server(struct Curl_easy *data, else if(result == CURLE_OPERATION_TIMEDOUT) { failf(data, "Failed to resolve %s '%s' with timeout after %" FMT_TIMEDIFF_T " ms", peertype, ehost->dispname, - curlx_timediff(curlx_now(), data->progress.t_startsingle)); + curlx_ptimediff_ms(Curl_pgrs_now(data), + &data->progress.t_startsingle)); return CURLE_OPERATION_TIMEDOUT; } else if(result) { @@ -3308,8 +3285,8 @@ static void reuse_conn(struct Curl_easy *data, * be new for this request even when we reuse an existing connection */ if(temp->user) { /* use the new username and password though */ - free(existing->user); - free(existing->passwd); + curlx_free(existing->user); + curlx_free(existing->passwd); existing->user = temp->user; existing->passwd = temp->passwd; temp->user = NULL; @@ -3320,10 +3297,10 @@ static void reuse_conn(struct Curl_easy *data, existing->bits.proxy_user_passwd = temp->bits.proxy_user_passwd; if(existing->bits.proxy_user_passwd) { /* use the new proxy username and proxy password though */ - free(existing->http_proxy.user); - free(existing->socks_proxy.user); - free(existing->http_proxy.passwd); - free(existing->socks_proxy.passwd); + curlx_free(existing->http_proxy.user); + curlx_free(existing->socks_proxy.user); + curlx_free(existing->http_proxy.passwd); + curlx_free(existing->socks_proxy.passwd); existing->http_proxy.user = temp->http_proxy.user; existing->socks_proxy.user = temp->socks_proxy.user; existing->http_proxy.passwd = temp->http_proxy.passwd; @@ -3354,7 +3331,7 @@ static void reuse_conn(struct Curl_easy *data, existing->conn_to_port = temp->conn_to_port; existing->remote_port = temp->remote_port; - free(existing->hostname_resolve); + curlx_free(existing->hostname_resolve); existing->hostname_resolve = temp->hostname_resolve; temp->hostname_resolve = NULL; @@ -3406,7 +3383,7 @@ static CURLcode create_conn(struct Curl_easy *data, /************************************************************* * Check input data *************************************************************/ - if(!data->state.url) { + if(!Curl_bufref_ptr(&data->state.url)) { result = CURLE_URL_MALFORMAT; goto out; } @@ -3436,7 +3413,7 @@ static CURLcode create_conn(struct Curl_easy *data, goto out; if(data->set.str[STRING_SASL_AUTHZID]) { - conn->sasl_authzid = strdup(data->set.str[STRING_SASL_AUTHZID]); + conn->sasl_authzid = curlx_strdup(data->set.str[STRING_SASL_AUTHZID]); if(!conn->sasl_authzid) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -3444,7 +3421,7 @@ static CURLcode create_conn(struct Curl_easy *data, } if(data->set.str[STRING_BEARER]) { - conn->oauth_bearer = strdup(data->set.str[STRING_BEARER]); + conn->oauth_bearer = curlx_strdup(data->set.str[STRING_BEARER]); if(!conn->oauth_bearer) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -3453,7 +3430,8 @@ static CURLcode create_conn(struct Curl_easy *data, #ifdef USE_UNIX_SOCKETS if(data->set.str[STRING_UNIX_SOCKET_PATH]) { - conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]); + conn->unix_domain_socket = + curlx_strdup(data->set.str[STRING_UNIX_SOCKET_PATH]); if(!conn->unix_domain_socket) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -3473,7 +3451,7 @@ static CURLcode create_conn(struct Curl_easy *data, * If the protocol is using SSL and HTTP proxy is used, we set * the tunnel_proxy bit. *************************************************************/ - if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy) + if((conn->given->flags & PROTOPT_SSL) && conn->bits.httpproxy) conn->bits.tunnel_proxy = TRUE; #endif @@ -3546,7 +3524,7 @@ static CURLcode create_conn(struct Curl_easy *data, * we set the tunnel_proxy bit. *************************************************************/ if((conn->bits.conn_to_host || conn->bits.conn_to_port) && - conn->bits.httpproxy) + conn->bits.httpproxy) conn->bits.tunnel_proxy = TRUE; #endif @@ -3660,6 +3638,7 @@ static CURLcode create_conn(struct Curl_easy *data, /* We have decided that we want a new connection. However, we may not be able to do that if we have reached the limit of how many connections we are allowed to open. */ + DEBUGF(infof(data, "new connection, bits.close=%d", conn->bits.close)); if(conn->handler->flags & PROTOPT_ALPN) { /* The protocol wants it, so set the bits if enabled in the easy handle @@ -3681,11 +3660,11 @@ static CURLcode create_conn(struct Curl_easy *data, connections_available = FALSE; break; case CPOOL_LIMIT_TOTAL: - if(data->master_mid != UINT_MAX) + if(data->master_mid != UINT32_MAX) CURL_TRC_M(data, "Allowing sub-requests (like DoH) to override " "max connection limit"); else { - infof(data, "No connections available, total of %ld reached.", + infof(data, "No connections available, total of %zu reached.", data->multi->max_total_connections); connections_available = FALSE; } @@ -3830,8 +3809,9 @@ CURLcode Curl_connect(struct Curl_easy *data, if(!result) { DEBUGASSERT(conn); + Curl_pgrsTime(data, TIMER_POSTQUEUE); if(reused) { - if(CONN_ATTACHED(conn) > 1) + if(conn->attached_xfers > 1) /* multiplexed */ *protocol_done = TRUE; } @@ -3879,7 +3859,6 @@ CURLcode Curl_connect(struct Curl_easy *data, CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn) { - /* if this is a pushed stream, we need this: */ CURLcode result; if(conn) { @@ -3899,9 +3878,7 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn) result = Curl_req_start(&data->req, data); if(!result) { - Curl_speedinit(data); - Curl_pgrsSetUploadCounter(data, 0); - Curl_pgrsSetDownloadCounter(data, 0); + Curl_pgrsReset(data); } return result; } @@ -3925,7 +3902,7 @@ static void priority_remove_child(struct Curl_easy *parent, DEBUGASSERT(pnode); if(pnode) { *pnext = pnode->next; - free(pnode); + curlx_free(pnode); } child->set.priority.parent = 0; @@ -3944,7 +3921,7 @@ CURLcode Curl_data_priority_add_child(struct Curl_easy *parent, struct Curl_data_prio_node **tail; struct Curl_data_prio_node *pnode; - pnode = calloc(1, sizeof(*pnode)); + pnode = curlx_calloc(1, sizeof(*pnode)); if(!pnode) return CURLE_OUT_OF_MEMORY; pnode->data = child; @@ -4005,7 +3982,6 @@ void Curl_data_priority_clear_state(struct Curl_easy *data) #endif /* USE_HTTP2 || USE_HTTP3 */ - CURLcode Curl_conn_meta_set(struct connectdata *conn, const char *key, void *meta_data, Curl_meta_dtor *meta_dtor) { diff --git a/lib/url.h b/lib/url.h index 82d869c5ff22..3a8d57c377f6 100644 --- a/lib/url.h +++ b/lib/url.h @@ -84,15 +84,13 @@ const struct Curl_handler *Curl_getn_scheme_handler(const char *scheme, * @param nowp NULL or pointer to time being checked against. */ bool Curl_conn_seems_dead(struct connectdata *conn, - struct Curl_easy *data, - struct curltime *nowp); + struct Curl_easy *data); /** * Perform upkeep operations on the connection. */ CURLcode Curl_conn_upkeep(struct Curl_easy *data, - struct connectdata *conn, - struct curltime *now); + struct connectdata *conn); /** * Always eval all arguments, return the first result != CURLE_OK. diff --git a/lib/urlapi.c b/lib/urlapi.c index 0a6ae5ba1a7c..747ac814bae1 100644 --- a/lib/urlapi.c +++ b/lib/urlapi.c @@ -29,7 +29,6 @@ #include "strcase.h" #include "url.h" #include "escape.h" -#include "curl_ctype.h" #include "curlx/inet_pton.h" #include "curlx/inet_ntop.h" #include "strdup.h" @@ -37,24 +36,20 @@ #include "curlx/strparse.h" #include "curl_memrchr.h" -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - #ifdef _WIN32 - /* MS-DOS/Windows style drive prefix, eg c: in c:foo */ -#define STARTS_WITH_DRIVE_PREFIX(str) \ - ((('a' <= str[0] && str[0] <= 'z') || \ +/* MS-DOS/Windows style drive prefix, eg c: in c:foo */ +#define STARTS_WITH_DRIVE_PREFIX(str) \ + ((('a' <= str[0] && str[0] <= 'z') || \ ('A' <= str[0] && str[0] <= 'Z')) && \ (str[1] == ':')) #endif - /* MS-DOS/Windows style drive prefix, optionally with - * a '|' instead of ':', followed by a slash or NUL */ -#define STARTS_WITH_URL_DRIVE_PREFIX(str) \ - ((('a' <= (str)[0] && (str)[0] <= 'z') || \ - ('A' <= (str)[0] && (str)[0] <= 'Z')) && \ - ((str)[1] == ':' || (str)[1] == '|') && \ +/* MS-DOS/Windows style drive prefix, optionally with + * a '|' instead of ':', followed by a slash or NUL */ +#define STARTS_WITH_URL_DRIVE_PREFIX(str) \ + ((('a' <= (str)[0] && (str)[0] <= 'z') || \ + ('A' <= (str)[0] && (str)[0] <= 'Z')) && \ + ((str)[1] == ':' || (str)[1] == '|') && \ ((str)[2] == '/' || (str)[2] == '\\' || (str)[2] == 0)) /* scheme is not URL encoded, the longest libcurl supported ones are... */ @@ -94,16 +89,16 @@ static CURLUcode parseurl_and_replace(const char *url, CURLU *u, static void free_urlhandle(struct Curl_URL *u) { - free(u->scheme); - free(u->user); - free(u->password); - free(u->options); - free(u->host); - free(u->zoneid); - free(u->port); - free(u->path); - free(u->query); - free(u->fragment); + curlx_free(u->scheme); + curlx_free(u->user); + curlx_free(u->password); + curlx_free(u->options); + curlx_free(u->host); + curlx_free(u->zoneid); + curlx_free(u->port); + curlx_free(u->path); + curlx_free(u->query); + curlx_free(u->fragment); } /* @@ -143,12 +138,12 @@ static CURLUcode urlencode_str(struct dynbuf *o, const char *url, /* we must add this with whitespace-replacing */ bool left = !query; const unsigned char *iptr; - const unsigned char *host_sep = (const unsigned char *) url; + const unsigned char *host_sep = (const unsigned char *)url; CURLcode result = CURLE_OK; if(!relative) { size_t n; - host_sep = (const unsigned char *) find_host_sep(url); + host_sep = (const unsigned char *)find_host_sep(url); /* output the first piece as-is */ n = (const char *)host_sep - url; @@ -164,7 +159,7 @@ static CURLUcode urlencode_str(struct dynbuf *o, const char *url, result = curlx_dyn_addn(o, "+", 1); } else if((*iptr < ' ') || (*iptr >= 0x7f)) { - unsigned char out[3]={'%'}; + unsigned char out[3] = { '%' }; Curl_hexbyte(&out[1], *iptr); result = curlx_dyn_addn(o, out, 3); } @@ -203,7 +198,7 @@ size_t Curl_is_absolute_url(const char *url, char *buf, size_t buflen, if(ISALPHA(url[0])) for(i = 1; i < MAX_SCHEME_LEN; ++i) { char s = url[i]; - if(s && (ISALNUM(s) || (s == '+') || (s == '-') || (s == '.') )) { + if(s && (ISALNUM(s) || (s == '+') || (s == '-') || (s == '.'))) { /* RFC 3986 3.1 explains: scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) */ @@ -384,17 +379,17 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u, result = CURLUE_USER_NOT_ALLOWED; goto out; } - free(u->user); + curlx_free(u->user); u->user = userp; } if(passwdp) { - free(u->password); + curlx_free(u->password); u->password = passwdp; } if(optionsp) { - free(u->options); + curlx_free(u->options); u->options = optionsp; } @@ -404,9 +399,9 @@ static CURLUcode parse_hostname_login(struct Curl_URL *u, out: - free(userp); - free(passwdp); - free(optionsp); + curlx_free(userp); + curlx_free(passwdp); + curlx_free(optionsp); u->user = NULL; u->password = NULL; u->options = NULL; @@ -457,9 +452,9 @@ UNITTEST CURLUcode Curl_parse_port(struct Curl_URL *u, struct dynbuf *host, if(curlx_str_number(&portptr, &port, 0xffff) || *portptr) return CURLUE_BAD_PORT_NUMBER; - u->portnum = (unsigned short) port; + u->portnum = (unsigned short)port; /* generate a new port number string to get rid of leading zeroes etc */ - free(u->port); + curlx_free(u->port); u->port = curl_maprintf("%" CURL_FORMAT_CURL_OFF_T, port); if(!u->port) return CURLUE_OUT_OF_MEMORY; @@ -497,7 +492,7 @@ static CURLUcode ipv6_parse(struct Curl_URL *u, char *hostname, if(!i || (']' != *h)) return CURLUE_BAD_IPV6; zoneid[i] = 0; - u->zoneid = strdup(zoneid); + u->zoneid = curlx_strdup(zoneid); if(!u->zoneid) return CURLUE_OUT_OF_MEMORY; hostname[len] = ']'; /* insert end bracket */ @@ -514,7 +509,7 @@ static CURLUcode ipv6_parse(struct Curl_URL *u, char *hostname, hostname[hlen] = 0; /* end the address there */ if(curlx_inet_pton(AF_INET6, hostname, dest) != 1) return CURLUE_BAD_IPV6; - if(curlx_inet_ntop(AF_INET6, dest, hostname, hlen)) { + if(curlx_inet_ntop(AF_INET6, dest, hostname, hlen + 1)) { hlen = strlen(hostname); /* might be shorter now */ hostname[hlen + 1] = 0; } @@ -567,7 +562,7 @@ static int ipv4_normalize(struct dynbuf *host) bool done = FALSE; int n = 0; const char *c = curlx_dyn_ptr(host); - unsigned int parts[4] = {0, 0, 0, 0}; + unsigned int parts[4] = { 0, 0, 0, 0 }; CURLcode result = CURLE_OK; if(*c == '[') @@ -675,7 +670,7 @@ static CURLUcode urldecode_host(struct dynbuf *host) return CURLUE_BAD_HOSTNAME; curlx_dyn_reset(host); result = curlx_dyn_addn(host, decoded, dlen); - free(decoded); + curlx_free(decoded); if(result) return cc2cu(result); } @@ -750,7 +745,7 @@ CURLUcode Curl_url_set_authority(CURLU *u, const char *authority) if(result) curlx_dyn_free(&host); else { - free(u->host); + curlx_free(u->host); u->host = curlx_dyn_ptr(&host); } return result; @@ -894,7 +889,7 @@ UNITTEST int dedotdotify(const char *input, size_t clen, char **outp) if(curlx_dyn_len(&out)) *outp = curlx_dyn_ptr(&out); else { - *outp = strdup(""); + *outp = curlx_strdup(""); if(!*outp) return 1; } @@ -924,7 +919,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags) goto fail; schemelen = Curl_is_absolute_url(url, schemebuf, sizeof(schemebuf), - flags & (CURLU_GUESS_SCHEME| + flags & (CURLU_GUESS_SCHEME | CURLU_DEFAULT_SCHEME)); /* handle the file: scheme */ @@ -940,7 +935,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags) path = &url[5]; pathlen = urllen - 5; - u->scheme = strdup("file"); + u->scheme = curlx_strdup("file"); if(!u->scheme) { result = CURLUE_OUT_OF_MEMORY; goto fail; @@ -1040,7 +1035,6 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags) pathlen--; } #endif - } else { /* clear path */ @@ -1073,7 +1067,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags) else { /* no scheme! */ - if(!(flags & (CURLU_DEFAULT_SCHEME|CURLU_GUESS_SCHEME))) { + if(!(flags & (CURLU_DEFAULT_SCHEME | CURLU_GUESS_SCHEME))) { result = CURLUE_BAD_SCHEME; goto fail; } @@ -1087,7 +1081,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags) } if(schemep) { - u->scheme = strdup(schemep); + u->scheme = curlx_strdup(schemep); if(!u->scheme) { result = CURLUE_OUT_OF_MEMORY; goto fail; @@ -1124,7 +1118,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags) else schemep = "http"; - u->scheme = strdup(schemep); + u->scheme = curlx_strdup(schemep); if(!u->scheme) { result = CURLUE_OUT_OF_MEMORY; goto fail; @@ -1197,7 +1191,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags) } else { /* single byte query */ - u->query = strdup(""); + u->query = curlx_strdup(""); if(!u->query) { result = CURLUE_OUT_OF_MEMORY; goto fail; @@ -1241,7 +1235,7 @@ static CURLUcode parseurl(const char *url, CURLU *u, unsigned int flags) goto fail; } if(dedot) { - free(u->path); + curlx_free(u->path); u->path = dedot; } } @@ -1277,21 +1271,21 @@ static CURLUcode parseurl_and_replace(const char *url, CURLU *u, */ CURLU *curl_url(void) { - return calloc(1, sizeof(struct Curl_URL)); + return curlx_calloc(1, sizeof(struct Curl_URL)); } void curl_url_cleanup(CURLU *u) { if(u) { free_urlhandle(u); - free(u); + curlx_free(u); } } #define DUP(dest, src, name) \ do { \ if(src->name) { \ - dest->name = strdup(src->name); \ + dest->name = curlx_strdup(src->name); \ if(!dest->name) \ goto fail; \ } \ @@ -1299,7 +1293,7 @@ void curl_url_cleanup(CURLU *u) CURLU *curl_url_dup(const CURLU *in) { - struct Curl_URL *u = calloc(1, sizeof(struct Curl_URL)); + struct Curl_URL *u = curlx_calloc(1, sizeof(struct Curl_URL)); if(u) { DUP(u, in, scheme); DUP(u, in, user); @@ -1322,8 +1316,8 @@ CURLU *curl_url_dup(const CURLU *in) } #ifndef USE_IDN -#define host_decode(x,y) CURLUE_LACKS_IDN -#define host_encode(x,y) CURLUE_LACKS_IDN +#define host_decode(x, y) CURLUE_LACKS_IDN +#define host_encode(x, y) CURLUE_LACKS_IDN #else static CURLUcode host_decode(const char *host, char **allochost) { @@ -1345,20 +1339,22 @@ static CURLUcode host_encode(const char *host, char **allochost) #endif static CURLUcode urlget_format(const CURLU *u, CURLUPart what, - const char *ptr, char **part, + const char *ptr, char **partp, bool plusdecode, unsigned int flags) { + CURLUcode uc = CURLUE_OK; size_t partlen = strlen(ptr); bool urldecode = (flags & CURLU_URLDECODE) ? 1 : 0; bool urlencode = (flags & CURLU_URLENCODE) ? 1 : 0; bool punycode = (flags & CURLU_PUNYCODE) && (what == CURLUPART_HOST); bool depunyfy = (flags & CURLU_PUNY2IDN) && (what == CURLUPART_HOST); - *part = Curl_memdup0(ptr, partlen); - if(!*part) + char *part = Curl_memdup0(ptr, partlen); + *partp = NULL; + if(!part) return CURLUE_OUT_OF_MEMORY; if(plusdecode) { /* convert + to space */ - char *plus = *part; + char *plus = part; size_t i = 0; for(i = 0; i < partlen; ++plus, i++) { if(*plus == '+') @@ -1370,46 +1366,43 @@ static CURLUcode urlget_format(const CURLU *u, CURLUPart what, size_t dlen; /* this unconditional rejection of control bytes is documented API behavior */ - CURLcode res = Curl_urldecode(*part, 0, &decoded, &dlen, REJECT_CTRL); - free(*part); - if(res) { - *part = NULL; + CURLcode res = Curl_urldecode(part, partlen, &decoded, &dlen, REJECT_CTRL); + curlx_free(part); + if(res) return CURLUE_URLDECODE; - } - *part = decoded; + part = decoded; partlen = dlen; } if(urlencode) { struct dynbuf enc; - CURLUcode uc; curlx_dyn_init(&enc, CURL_MAX_INPUT_LENGTH); - uc = urlencode_str(&enc, *part, partlen, TRUE, what == CURLUPART_QUERY); + uc = urlencode_str(&enc, part, partlen, TRUE, what == CURLUPART_QUERY); + curlx_free(part); if(uc) return uc; - free(*part); - *part = curlx_dyn_ptr(&enc); + part = curlx_dyn_ptr(&enc); } else if(punycode) { if(!Curl_is_ASCII_name(u->host)) { - char *allochost = NULL; - CURLUcode ret = host_decode(*part, &allochost); - if(ret) - return ret; - free(*part); - *part = allochost; + char *punyversion = NULL; + uc = host_decode(part, &punyversion); + curlx_free(part); + if(uc) + return uc; + part = punyversion; } } else if(depunyfy) { if(Curl_is_ASCII_name(u->host)) { - char *allochost = NULL; - CURLUcode ret = host_encode(*part, &allochost); - if(ret) - return ret; - free(*part); - *part = allochost; + char *unpunified = NULL; + uc = host_encode(part, &unpunified); + curlx_free(part); + if(uc) + return uc; + part = unpunified; } } - + *partp = part; return CURLUE_OK; } @@ -1521,7 +1514,7 @@ static CURLUcode urlget_url(const CURLU *u, char **part, unsigned int flags) u->query ? u->query : "", show_fragment ? "#": "", u->fragment ? u->fragment : ""); - free(allochost); + curlx_free(allochost); } if(!url) return CURLUE_OUT_OF_MEMORY; @@ -1667,7 +1660,7 @@ static CURLUcode set_url_port(CURLU *u, const char *provided_port) tmp = curl_maprintf("%" CURL_FORMAT_CURL_OFF_T, port); if(!tmp) return CURLUE_OUT_OF_MEMORY; - free(u->port); + curlx_free(u->port); u->port = tmp; u->portnum = (unsigned short)port; return CURLUE_OK; @@ -1688,26 +1681,35 @@ static CURLUcode set_url(CURLU *u, const char *url, size_t part_size, if(!part_size) { /* a blank URL is not a valid URL unless we already have a complete one and this is a redirect */ - if(!curl_url_get(u, CURLUPART_URL, &oldurl, flags)) { + uc = curl_url_get(u, CURLUPART_URL, &oldurl, flags); + if(!uc) { /* success, meaning the "" is a fine relative URL, but nothing changes */ - free(oldurl); + curlx_free(oldurl); return CURLUE_OK; } + if(uc == CURLUE_OUT_OF_MEMORY) + return uc; return CURLUE_MALFORMED_INPUT; } - /* if the new thing is absolute or the old one is not (we could not get an - * absolute URL in 'oldurl'), then replace the existing with the new. */ + /* if the new URL is absolute replace the existing with the new. */ if(Curl_is_absolute_url(url, NULL, 0, - flags & (CURLU_GUESS_SCHEME|CURLU_DEFAULT_SCHEME)) - || curl_url_get(u, CURLUPART_URL, &oldurl, flags)) { + flags & (CURLU_GUESS_SCHEME | CURLU_DEFAULT_SCHEME))) return parseurl_and_replace(url, u, flags); - } + + /* if the old URL is incomplete (we cannot get an absolute URL in + 'oldurl'), replace the existing with the new */ + uc = curl_url_get(u, CURLUPART_URL, &oldurl, flags); + if(uc == CURLUE_OUT_OF_MEMORY) + return uc; + else if(uc) + return parseurl_and_replace(url, u, flags); + DEBUGASSERT(oldurl); /* it is set here */ /* apply the relative part to create a new URL */ uc = redirect_url(oldurl, url, u, flags); - free(oldurl); + curlx_free(oldurl); return uc; } @@ -1761,11 +1763,24 @@ static CURLUcode urlset_clear(CURLU *u, CURLUPart what) static bool allowed_in_path(unsigned char x) { switch(x) { - case '!': case '$': case '&': case '\'': - case '(': case ')': case '{': case '}': - case '[': case ']': case '*': case '+': - case ',': case ';': case '=': case ':': - case '@': case '/': + case '!': + case '$': + case '&': + case '\'': + case '(': + case ')': + case '{': + case '}': + case '[': + case ']': + case '*': + case '+': + case ',': + case ';': + case '=': + case ':': + case '@': + case '/': return TRUE; } return FALSE; @@ -1874,7 +1889,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what, return cc2cu(result); } else { - unsigned char out[3]={'%'}; + unsigned char out[3] = { '%' }; Curl_hexbyte(&out[1], *i); result = curlx_dyn_addn(&enc, out, 3); if(result) @@ -1907,7 +1922,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what, none is present at the end of the existing query already */ size_t querylen = u->query ? strlen(u->query) : 0; - bool addamperand = querylen && (u->query[querylen -1] != '&'); + bool addamperand = querylen && (u->query[querylen - 1] != '&'); if(querylen) { struct dynbuf qbuf; curlx_dyn_init(&qbuf, CURL_MAX_INPUT_LENGTH); @@ -1922,7 +1937,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what, if(curlx_dyn_add(&qbuf, newp)) goto nomem; curlx_dyn_free(&enc); - free(*storep); + curlx_free(*storep); *storep = curlx_dyn_ptr(&qbuf); return CURLUE_OK; nomem: @@ -1941,7 +1956,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what, if(!n) bad = TRUE; /* empty hostname is not okay */ else if(!urlencode) { - /* if the host name part was not URL encoded here, it was set ready + /* if the hostname part was not URL encoded here, it was set ready URL encoded so we need to decode it to check */ size_t dlen; char *decoded = NULL; @@ -1949,7 +1964,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what, Curl_urldecode(newp, n, &decoded, &dlen, REJECT_CTRL); if(result || hostname_check(u, decoded, dlen)) bad = TRUE; - free(decoded); + curlx_free(decoded); } else if(hostname_check(u, (char *)CURL_UNCONST(newp), n)) bad = TRUE; @@ -1960,7 +1975,7 @@ CURLUcode curl_url_set(CURLU *u, CURLUPart what, } } - free(*storep); + curlx_free(*storep); *storep = (char *)CURL_UNCONST(newp); } return CURLUE_OK; diff --git a/lib/urldata.h b/lib/urldata.h index c7e19201fe88..3940c4d391da 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -28,40 +28,40 @@ #include "curl_setup.h" -#define PORT_FTP 21 -#define PORT_FTPS 990 +#define PORT_FTP 21 +#define PORT_FTPS 990 #define PORT_TELNET 23 -#define PORT_HTTP 80 -#define PORT_HTTPS 443 -#define PORT_DICT 2628 -#define PORT_LDAP 389 -#define PORT_LDAPS 636 -#define PORT_TFTP 69 -#define PORT_SSH 22 -#define PORT_IMAP 143 -#define PORT_IMAPS 993 -#define PORT_POP3 110 -#define PORT_POP3S 995 -#define PORT_SMB 445 -#define PORT_SMBS 445 -#define PORT_SMTP 25 -#define PORT_SMTPS 465 /* sometimes called SSMTP */ -#define PORT_RTSP 554 -#define PORT_RTMP 1935 -#define PORT_RTMPT PORT_HTTP -#define PORT_RTMPS PORT_HTTPS +#define PORT_HTTP 80 +#define PORT_HTTPS 443 +#define PORT_DICT 2628 +#define PORT_LDAP 389 +#define PORT_LDAPS 636 +#define PORT_TFTP 69 +#define PORT_SSH 22 +#define PORT_IMAP 143 +#define PORT_IMAPS 993 +#define PORT_POP3 110 +#define PORT_POP3S 995 +#define PORT_SMB 445 +#define PORT_SMBS 445 +#define PORT_SMTP 25 +#define PORT_SMTPS 465 /* sometimes called SSMTP */ +#define PORT_RTSP 554 +#define PORT_RTMP 1935 +#define PORT_RTMPT PORT_HTTP +#define PORT_RTMPS PORT_HTTPS #define PORT_GOPHER 70 -#define PORT_MQTT 1883 +#define PORT_MQTT 1883 struct curl_trc_featt; #ifdef USE_ECH /* CURLECH_ bits for the tls_ech option */ -# define CURLECH_DISABLE (1<<0) -# define CURLECH_GREASE (1<<1) -# define CURLECH_ENABLE (1<<2) -# define CURLECH_HARD (1<<3) -# define CURLECH_CLA_CFG (1<<4) +# define CURLECH_DISABLE (1 << 0) +# define CURLECH_GREASE (1 << 1) +# define CURLECH_ENABLE (1 << 2) +# define CURLECH_HARD (1 << 3) +# define CURLECH_CLA_CFG (1 << 4) #endif #ifndef CURL_DISABLE_WEBSOCKETS @@ -70,8 +70,8 @@ struct curl_trc_featt; * platforms that have a >= 64-bit type and then we use such a type for the * protocol fields in the protocol handler. */ -#define CURLPROTO_WS (1L<<30) -#define CURLPROTO_WSS ((curl_prot_t)1<<31) +#define CURLPROTO_WS (1L << 30) +#define CURLPROTO_WSS ((curl_prot_t)1 << 31) #else #define CURLPROTO_WS 0L #define CURLPROTO_WSS 0L @@ -107,15 +107,15 @@ typedef unsigned int curl_prot_t; /* Convenience defines for checking protocols or their SSL based version. Each protocol handler should only ever have a single CURLPROTO_ in its protocol field. */ -#define PROTO_FAMILY_HTTP (CURLPROTO_HTTP|CURLPROTO_HTTPS|CURLPROTO_WS| \ +#define PROTO_FAMILY_HTTP (CURLPROTO_HTTP | CURLPROTO_HTTPS | CURLPROTO_WS | \ CURLPROTO_WSS) -#define PROTO_FAMILY_FTP (CURLPROTO_FTP|CURLPROTO_FTPS) -#define PROTO_FAMILY_POP3 (CURLPROTO_POP3|CURLPROTO_POP3S) -#define PROTO_FAMILY_SMB (CURLPROTO_SMB|CURLPROTO_SMBS) -#define PROTO_FAMILY_SMTP (CURLPROTO_SMTP|CURLPROTO_SMTPS) -#define PROTO_FAMILY_SSH (CURLPROTO_SCP|CURLPROTO_SFTP) +#define PROTO_FAMILY_FTP (CURLPROTO_FTP | CURLPROTO_FTPS) +#define PROTO_FAMILY_POP3 (CURLPROTO_POP3 | CURLPROTO_POP3S) +#define PROTO_FAMILY_SMB (CURLPROTO_SMB | CURLPROTO_SMBS) +#define PROTO_FAMILY_SMTP (CURLPROTO_SMTP | CURLPROTO_SMTPS) +#define PROTO_FAMILY_SSH (CURLPROTO_SCP | CURLPROTO_SFTP) -#if !defined(CURL_DISABLE_FTP) || defined(USE_SSH) || \ +#if !defined(CURL_DISABLE_FTP) || defined(USE_SSH) || \ !defined(CURL_DISABLE_POP3) /* these protocols support CURLOPT_DIRLISTONLY */ #define CURL_LIST_ONLY_PROTOCOL 1 @@ -127,13 +127,12 @@ typedef unsigned int curl_prot_t; #define MAX_IPADR_LEN sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") /* Default FTP/IMAP etc response timeout in milliseconds */ -#define RESP_TIMEOUT (120*1000) +#define RESP_TIMEOUT (60 * 1000) /* Max string input length is a precaution against abuse and to detect junk input easier and better. */ #define CURL_MAX_INPUT_LENGTH 8000000 - #include "cookie.h" #include "psl.h" #include "formdata.h" @@ -147,21 +146,21 @@ typedef unsigned int curl_prot_t; #include "curlx/timeval.h" -#include - #include "http_chunks.h" /* for the structs and enum stuff */ #include "hostip.h" #include "hash.h" #include "splay.h" #include "curlx/dynbuf.h" +#include "bufref.h" #include "dynhds.h" #include "request.h" +#include "ratelimit.h" #include "netrc.h" /* On error return, the value of `pnwritten` has no meaning */ typedef CURLcode (Curl_send)(struct Curl_easy *data, /* transfer */ int sockindex, /* socketindex */ - const void *buf, /* data to write */ + const uint8_t *buf, /* data to write */ size_t len, /* amount to send */ bool eos, /* last chunk */ size_t *pnwritten); /* how much sent */ @@ -178,7 +177,6 @@ typedef CURLcode (Curl_recv)(struct Curl_easy *data, /* transfer */ #include "smtp.h" #include "ftp.h" #include "file.h" -#include "vssh/ssh.h" #include "http.h" #include "rtsp.h" #include "smb.h" @@ -190,8 +188,11 @@ typedef CURLcode (Curl_recv)(struct Curl_easy *data, /* transfer */ #ifdef HAVE_GSSAPI # ifdef HAVE_GSSGNU # include -# else +# elif defined(HAVE_GSSAPI_H) +# include +# else /* MIT Kerberos */ # include +# include /* for GSS_C_CHANNEL_BOUND_FLAG, in 1.19+ */ # endif #endif @@ -213,8 +214,8 @@ typedef CURLcode (Curl_recv)(struct Curl_easy *data, /* transfer */ larger buffers can help further, but this is deemed a fair memory/speed compromise. */ #define UPLOADBUFFER_DEFAULT 65536 -#define UPLOADBUFFER_MAX (2*1024*1024) -#define UPLOADBUFFER_MIN CURL_MAX_WRITE_SIZE +#define UPLOADBUFFER_MAX (2 * 1024 * 1024) +#define UPLOADBUFFER_MIN CURL_MAX_WRITE_SIZE #define CURLEASY_MAGIC_NUMBER 0xc0dedbadU #ifdef DEBUGBUILD @@ -222,7 +223,7 @@ typedef CURLcode (Curl_recv)(struct Curl_easy *data, /* transfer */ * are not NULL, but no longer have the MAGIC touch. This gives * us early warning on things only discovered by valgrind otherwise. */ #define GOOD_EASY_HANDLE(x) \ - (((x) && ((x)->magic == CURLEASY_MAGIC_NUMBER))? TRUE: \ + (((x) && ((x)->magic == CURLEASY_MAGIC_NUMBER)) ? TRUE : \ (DEBUGASSERT(!(x)), FALSE)) #else #define GOOD_EASY_HANDLE(x) \ @@ -234,7 +235,7 @@ struct ssl_backend_data; struct Curl_ssl_scache_entry; struct ssl_primary_config { - char *CApath; /* certificate dir (does not work on Windows) */ + char *CApath; /* certificate directory (does not work on Windows) */ char *CAfile; /* certificate to verify peer against */ char *issuercert; /* optional issuer certificate filename */ char *clientcert; @@ -265,19 +266,19 @@ struct ssl_config_data { long certverifyresult; /* result from the certificate verification */ curl_ssl_ctx_callback fsslctx; /* function to initialize ssl ctx */ void *fsslctxp; /* parameter for call back */ - char *cert_type; /* format for certificate (default: PEM)*/ + char *cert_type; /* format for certificate (default: PEM) */ char *key; /* private key filename */ struct curl_blob *key_blob; char *key_type; /* format for private key (default: PEM) */ char *key_passwd; /* plain text private key password */ BIT(certinfo); /* gather lots of certificate info */ - BIT(earlydata); /* use tls1.3 early data */ + BIT(earlydata); /* use TLS 1.3 early data */ BIT(enable_beast); /* allow this flaw for interoperability's sake */ BIT(no_revoke); /* disable SSL certificate revocation checks */ BIT(no_partialchain); /* do not accept partial certificate chains */ BIT(revoke_best_effort); /* ignore SSL revocation offline/missing revocation list errors */ - BIT(native_ca_store); /* use the native ca store of operating system */ + BIT(native_ca_store); /* use the native CA store of operating system */ BIT(auto_client_cert); /* automatically locate and use a client certificate for authentication (Schannel) */ BIT(custom_cafile); /* application has set custom CA file */ @@ -419,33 +420,14 @@ struct hostname { * Flags on the keepon member of the Curl_transfer_keeper */ -#define KEEP_NONE 0 -#define KEEP_RECV (1<<0) /* there is or may be data to read */ -#define KEEP_SEND (1<<1) /* there is or may be data to write */ -#define KEEP_RECV_HOLD (1<<2) /* when set, no reading should be done but there - might still be data to read */ -#define KEEP_SEND_HOLD (1<<3) /* when set, no writing should be done but there - might still be data to write */ -#define KEEP_RECV_PAUSE (1<<4) /* reading is paused */ -#define KEEP_SEND_PAUSE (1<<5) /* writing is paused */ - -/* KEEP_SEND_TIMED is set when the transfer should attempt sending - * at timer (or other) events. A transfer waiting on a timer will - * remove KEEP_SEND to suppress POLLOUTs of the connection. - * Adding KEEP_SEND_TIMED will then attempt to send whenever the transfer - * enters the "readwrite" loop, e.g. when a timer fires. - * This is used in HTTP for 'Expect: 100-continue' waiting. */ -#define KEEP_SEND_TIMED (1<<6) - -#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) +#define KEEP_NONE 0 +#define KEEP_RECV (1 << 0) /* there is or may be data to read */ +#define KEEP_SEND (1 << 1) /* there is or may be data to write */ + +/* transfer wants to send */ +#define CURL_WANT_SEND(data) ((data)->req.keepon & KEEP_SEND) +/* transfer wants to receive */ +#define CURL_WANT_RECV(data) ((data)->req.keepon & KEEP_RECV) #define FIRSTSOCKET 0 #define SECONDARYSOCKET 1 @@ -542,11 +524,11 @@ struct Curl_handler { CURLcode (*follow)(struct Curl_easy *data, const char *newurl, followtype type); - int defport; /* Default port. */ - curl_prot_t protocol; /* See CURLPROTO_* - this needs to be the single - specific protocol bit */ - curl_prot_t family; /* single bit for protocol family; basically the - non-TLS name of the protocol this is */ + uint16_t defport; /* Default port. */ + curl_prot_t protocol; /* See CURLPROTO_* - this needs to be the single + specific protocol bit */ + curl_prot_t family; /* single bit for protocol family; basically the + non-TLS name of the protocol this is */ unsigned int flags; /* Extra particular characteristics, see PROTOPT_* */ }; @@ -574,13 +556,14 @@ struct Curl_handler { #define PROTOPT_PROXY_AS_HTTP (1<<11) /* allow this non-HTTP scheme over a HTTP proxy as HTTP proxies may know this protocol and act as a gateway */ -#define PROTOPT_WILDCARD (1<<12) /* protocol supports wildcard matching */ +#define PROTOPT_WILDCARD (1<<12) /* protocol supports wildcard matching */ #define PROTOPT_USERPWDCTRL (1<<13) /* Allow "control bytes" (< 32 ASCII) in username and password */ -#define PROTOPT_NOTCPPROXY (1<<14) /* this protocol cannot proxy over TCP */ -#define PROTOPT_SSL_REUSE (1<<15) /* this protocol may reuse an existing - SSL connection in the same family - without having PROTOPT_SSL. */ +#define PROTOPT_NOTCPPROXY (1<<14) /* this protocol cannot proxy over TCP */ +#define PROTOPT_SSL_REUSE (1<<15) /* this protocol may reuse an existing + SSL connection in the same family + without having PROTOPT_SSL. */ +#define PROTOPT_CONN_REUSE (1<<16) /* this protocol can reuse connections */ #define CONNCHECK_NONE 0 /* No checks */ #define CONNCHECK_ISDEAD (1<<0) /* Check if the connection is dead. */ @@ -589,26 +572,33 @@ struct Curl_handler { #define CONNRESULT_NONE 0 /* No extra information. */ #define CONNRESULT_DEAD (1<<0) /* The connection is dead. */ +#define TRNSPRT_NONE 0 +#define TRNSPRT_TCP 3 +#define TRNSPRT_UDP 4 +#define TRNSPRT_QUIC 5 +#define TRNSPRT_UNIX 6 + struct ip_quadruple { char remote_ip[MAX_IPADR_LEN]; char local_ip[MAX_IPADR_LEN]; - int remote_port; - int local_port; + uint16_t remote_port; + uint16_t local_port; + uint8_t transport; }; +#define CUR_IP_QUAD_HAS_PORTS(x) \ + (((x)->transport == TRNSPRT_TCP) || \ + ((x)->transport == TRNSPRT_UDP) || \ + ((x)->transport == TRNSPRT_QUIC)) + struct proxy_info { struct hostname host; - int port; + uint16_t port; unsigned char proxytype; /* what kind of proxy that is in use */ char *user; /* proxy username string, allocated */ char *passwd; /* proxy password string, allocated */ }; -#define TRNSPRT_TCP 3 -#define TRNSPRT_UDP 4 -#define TRNSPRT_QUIC 5 -#define TRNSPRT_UNIX 6 - /* * The connectdata struct contains all fields and variables that should be * unique for an entire connection. @@ -624,8 +614,7 @@ struct connectdata { handle is still used by one or more easy handles and can only used by any other easy handle without careful consideration (== only for multiplexing) and it cannot be used by another multi handle! */ -#define CONN_INUSE(c) (!Curl_uint_spbset_empty(&(c)->xfers_attached)) -#define CONN_ATTACHED(c) Curl_uint_spbset_count(&(c)->xfers_attached) +#define CONN_INUSE(c) (!!(c)->attached_xfers) /**** Fields set when inited and not modified again */ curl_off_t connection_id; /* Contains a unique number to make it easier to @@ -685,7 +674,6 @@ struct connectdata { was used on this connection. */ struct curltime keepalive; - struct uint_spbset xfers_attached; /* mids of attached transfers */ /* A connection cache from a SHARE might be used in several multi handles. * We MUST not reuse connections that are running in another multi, * for concurrency reasons. That multi might run in another thread. @@ -720,7 +708,6 @@ struct connectdata { wrong connections. */ char *localdev; unsigned short localportrange; - int waitfor; /* current READ/WRITE bits to wait for */ #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) int socks5_gssapi_enctype; #endif @@ -728,6 +715,9 @@ struct connectdata { int remote_port; /* the remote port, not the proxy port! */ int conn_to_port; /* the remote port to connect to. valid only if bits.conn_to_port is set */ + + uint32_t attached_xfers; /* # of attached easy handles */ + #ifdef USE_IPV6 unsigned int scope_id; /* Scope id for IPv6 */ #endif @@ -748,14 +738,14 @@ struct connectdata { #ifndef CURL_DISABLE_PROXY #define CURL_CONN_HOST_DISPNAME(c) \ - ((c)->bits.socksproxy ? (c)->socks_proxy.host.dispname : \ - (c)->bits.httpproxy ? (c)->http_proxy.host.dispname : \ - (c)->bits.conn_to_host ? (c)->conn_to_host.dispname : \ - (c)->host.dispname) + ((c)->bits.socksproxy ? (c)->socks_proxy.host.dispname : \ + (c)->bits.httpproxy ? (c)->http_proxy.host.dispname : \ + (c)->bits.conn_to_host ? (c)->conn_to_host.dispname : \ + (c)->host.dispname) #else #define CURL_CONN_HOST_DISPNAME(c) \ - (c)->bits.conn_to_host ? (c)->conn_to_host.dispname : \ - (c)->host.dispname + (c)->bits.conn_to_host ? (c)->conn_to_host.dispname : \ + (c)->host.dispname #endif /* The end of connectdata. */ @@ -801,19 +791,15 @@ struct PureInfo { BIT(used_proxy); /* the transfer used a proxy */ }; -struct pgrs_measure { - struct curltime start; /* when measure started */ - curl_off_t start_size; /* the 'cur_size' the measure started at */ -}; - struct pgrs_dir { curl_off_t total_size; /* total expected bytes */ curl_off_t cur_size; /* transferred bytes so far */ curl_off_t speed; /* bytes per second transferred */ - struct pgrs_measure limit; + struct Curl_rlimit rlimit; /* speed limiting / pausing */ }; struct Progress { + struct curltime now; /* current time of processing */ time_t lastshow; /* time() of the last displayed progress meter or NULL to force redraw at next call */ struct pgrs_dir ul; @@ -839,10 +825,10 @@ struct Progress { struct curltime t_startqueue; struct curltime t_acceptdata; -#define CURR_TIME (5 + 1) /* 6 entries for 5 seconds */ +#define CURL_SPEED_RECORDS (5 + 1) /* 6 entries for 5 seconds */ - curl_off_t speeder[ CURR_TIME ]; - struct curltime speeder_time[ CURR_TIME ]; + curl_off_t speed_amount[CURL_SPEED_RECORDS]; + struct curltime speed_time[CURL_SPEED_RECORDS]; unsigned char speeder_c; BIT(hide); BIT(ul_size_known); @@ -853,19 +839,19 @@ struct Progress { }; typedef enum { - RTSPREQ_NONE, /* first in list */ - RTSPREQ_OPTIONS, - RTSPREQ_DESCRIBE, - RTSPREQ_ANNOUNCE, - RTSPREQ_SETUP, - RTSPREQ_PLAY, - RTSPREQ_PAUSE, - RTSPREQ_TEARDOWN, - RTSPREQ_GET_PARAMETER, - RTSPREQ_SET_PARAMETER, - RTSPREQ_RECORD, - RTSPREQ_RECEIVE, - RTSPREQ_LAST /* last in list */ + RTSPREQ_NONE, /* first in list */ + RTSPREQ_OPTIONS, + RTSPREQ_DESCRIBE, + RTSPREQ_ANNOUNCE, + RTSPREQ_SETUP, + RTSPREQ_PLAY, + RTSPREQ_PAUSE, + RTSPREQ_TEARDOWN, + RTSPREQ_GET_PARAMETER, + RTSPREQ_SET_PARAMETER, + RTSPREQ_RECORD, + RTSPREQ_RECEIVE, + RTSPREQ_LAST /* last in list */ } Curl_RtspReq; struct auth { @@ -925,7 +911,6 @@ typedef enum { EXPIRE_LAST /* not an actual timer, used as a marker only */ } expire_id; - typedef enum { TRAILERS_NONE, TRAILERS_INITIALIZED, @@ -933,7 +918,6 @@ typedef enum { TRAILERS_DONE } trailers_state; - /* * One instance for each timeout an easy handle can set. */ @@ -1040,8 +1024,8 @@ struct UrlState { void *in; /* CURLOPT_READDATA */ CURLU *uh; /* URL handle for the current parsed URL */ struct urlpieces up; - char *url; /* work URL, copied from UserDefined */ - char *referer; /* referer string */ + struct bufref url; /* work URL, initially copied from UserDefined */ + struct bufref referer; /* referer string */ struct curl_slist *resolve; /* set to point to the set.resolve list when this should be dealt with in pretransfer */ #ifndef CURL_DISABLE_HTTP @@ -1137,8 +1121,6 @@ struct UrlState { #ifdef CURL_LIST_ONLY_PROTOCOL BIT(list_only); /* list directory contents */ #endif - BIT(url_alloc); /* URL string is malloc()'ed */ - BIT(referer_alloc); /* referer string is malloc()ed */ BIT(wildcard_resolve); /* Set to true if any resolve change is a wildcard */ BIT(upload); /* upload request */ BIT(internal); /* internal: true if this easy handle was created for @@ -1149,6 +1131,8 @@ struct UrlState { BIT(http_hd_te); /* Added HTTP header TE: */ BIT(http_hd_upgrade); /* Added HTTP header Upgrade: */ BIT(http_hd_h2_settings); /* Added HTTP header H2Settings: */ + BIT(maybe_folded); + BIT(leading_unfold); /* unfold started, this is the leading bytes */ #endif }; @@ -1174,8 +1158,8 @@ enum dupstring { STRING_SSL_PINNEDPUBLICKEY, /* public key file to verify peer against */ STRING_SSL_CIPHER_LIST, /* list of ciphers to use */ STRING_SSL_CIPHER13_LIST, /* list of TLS 1.3 ciphers to use */ - STRING_SSL_CRLFILE, /* crl file to check certificate */ - STRING_SSL_ISSUERCERT, /* issuer cert file to check certificate */ + STRING_SSL_CRLFILE, /* CRL file to check certificate */ + STRING_SSL_ISSUERCERT, /* issuer cert file to check certificate */ STRING_SERVICE_NAME, /* Service name */ #ifndef CURL_DISABLE_PROXY STRING_CERT_PROXY, /* client certificate filename */ @@ -1188,7 +1172,7 @@ enum dupstring { STRING_SSL_PINNEDPUBLICKEY_PROXY, /* public key file to verify proxy */ STRING_SSL_CIPHER_LIST_PROXY, /* list of ciphers to use */ STRING_SSL_CIPHER13_LIST_PROXY, /* list of TLS 1.3 ciphers to use */ - STRING_SSL_CRLFILE_PROXY, /* crl file to check certificate */ + STRING_SSL_CRLFILE_PROXY, /* CRL file to check certificate */ STRING_SSL_ISSUERCERT_PROXY, /* issuer cert file to check certificate */ STRING_PROXY_SERVICE_NAME, /* Proxy service name */ #endif @@ -1310,7 +1294,6 @@ enum dupblob { BLOB_LAST }; - struct UserDefined { FILE *err; /* the stderr user data goes here */ void *debugdata; /* the data that will be passed to fdebug */ @@ -1382,7 +1365,7 @@ struct UserDefined { #ifndef CURL_DISABLE_PROXY struct ssl_config_data proxy_ssl; /* user defined SSL stuff for proxy */ struct curl_slist *proxyheaders; /* linked list of extra CONNECT headers */ - unsigned short proxyport; /* If non-zero, use this port number by + uint16_t proxyport; /* If non-zero, use this port number by default. If the proxy string features a ":[port]" that one will override this. */ unsigned char proxytype; /* what kind of proxy */ @@ -1650,8 +1633,8 @@ struct Curl_easy { /* once an easy handle is added to a multi, either explicitly by the * libcurl application or implicitly during `curl_easy_perform()`, * a unique identifier inside this one multi instance. */ - unsigned int mid; - unsigned int master_mid; /* if set, this transfer belongs to a master */ + uint32_t mid; + uint32_t master_mid; /* if set, this transfer belongs to a master */ multi_sub_xfer_done_cb *sub_xfer_done; struct connectdata *conn; diff --git a/lib/vauth/cleartext.c b/lib/vauth/cleartext.c index dcfb13912d27..a3e83d74f475 100644 --- a/lib/vauth/cleartext.c +++ b/lib/vauth/cleartext.c @@ -27,20 +27,11 @@ #include "../curl_setup.h" -#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_SMTP) || \ - !defined(CURL_DISABLE_POP3) || \ +#if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_SMTP) || \ + !defined(CURL_DISABLE_POP3) || \ (!defined(CURL_DISABLE_LDAP) && defined(USE_OPENLDAP)) -#include -#include "../urldata.h" - #include "vauth.h" -#include "../curlx/warnless.h" -#include "../sendf.h" - -/* The last #include files should be: */ -#include "../curl_memory.h" -#include "../memdebug.h" /* * Curl_auth_create_plain_message() @@ -62,35 +53,24 @@ CURLcode Curl_auth_create_plain_message(const char *authzid, const char *passwd, struct bufref *out) { - char *plainauth; - size_t plainlen; - size_t zlen; - size_t clen; - size_t plen; + size_t len; + char *auth; - zlen = (authzid == NULL ? 0 : strlen(authzid)); - clen = strlen(authcid); - plen = strlen(passwd); + size_t zlen = (authzid == NULL ? 0 : strlen(authzid)); + size_t clen = strlen(authcid); + size_t plen = strlen(passwd); - /* Compute binary message length. Check for overflows. */ - if((zlen > SIZE_MAX/4) || (clen > SIZE_MAX/4) || - (plen > (SIZE_MAX/2 - 2))) - return CURLE_OUT_OF_MEMORY; - plainlen = zlen + clen + plen + 2; + if((zlen > CURL_MAX_INPUT_LENGTH) || (clen > CURL_MAX_INPUT_LENGTH) || + (plen > CURL_MAX_INPUT_LENGTH)) + return CURLE_TOO_LARGE; - plainauth = malloc(plainlen + 1); - if(!plainauth) - return CURLE_OUT_OF_MEMORY; + len = zlen + clen + plen + 2; - /* Calculate the reply */ - if(zlen) - memcpy(plainauth, authzid, zlen); - plainauth[zlen] = '\0'; - memcpy(plainauth + zlen + 1, authcid, clen); - plainauth[zlen + clen + 1] = '\0'; - memcpy(plainauth + zlen + clen + 2, passwd, plen); - plainauth[plainlen] = '\0'; - Curl_bufref_set(out, plainauth, plainlen, curl_free); + auth = curl_maprintf("%s%c%s%c%s", authzid ? authzid : "", '\0', + authcid, '\0', passwd); + if(!auth) + return CURLE_OUT_OF_MEMORY; + Curl_bufref_set(out, auth, len, curl_free); return CURLE_OK; } @@ -125,8 +105,7 @@ void Curl_auth_create_login_message(const char *valuep, struct bufref *out) * * Returns void. */ -void Curl_auth_create_external_message(const char *user, - struct bufref *out) +void Curl_auth_create_external_message(const char *user, struct bufref *out) { /* This is the same formatting as the login message */ Curl_auth_create_login_message(user, out); diff --git a/lib/vauth/cram.c b/lib/vauth/cram.c index 2754ddc4a29f..8aa4055231cd 100644 --- a/lib/vauth/cram.c +++ b/lib/vauth/cram.c @@ -28,17 +28,9 @@ #ifndef CURL_DISABLE_DIGEST_AUTH -#include -#include "../urldata.h" - #include "vauth.h" #include "../curl_hmac.h" #include "../curl_md5.h" -#include "../curlx/warnless.h" - -/* The last #include files should be: */ -#include "../curl_memory.h" -#include "../memdebug.h" /* @@ -67,14 +59,14 @@ CURLcode Curl_auth_create_cram_md5_message(const struct bufref *chlg, /* Compute the digest using the password as the key */ ctxt = Curl_HMAC_init(&Curl_HMAC_MD5, - (const unsigned char *) passwdp, + (const unsigned char *)passwdp, curlx_uztoui(strlen(passwdp))); if(!ctxt) return CURLE_OUT_OF_MEMORY; /* Update the digest with the given challenge */ if(Curl_bufref_len(chlg)) - Curl_HMAC_update(ctxt, Curl_bufref_ptr(chlg), + Curl_HMAC_update(ctxt, Curl_bufref_uptr(chlg), curlx_uztoui(Curl_bufref_len(chlg))); /* Finalise the digest */ diff --git a/lib/vauth/digest.c b/lib/vauth/digest.c index 0a0b3580ed09..c67be1dd8484 100644 --- a/lib/vauth/digest.c +++ b/lib/vauth/digest.c @@ -29,25 +29,15 @@ #ifndef CURL_DISABLE_DIGEST_AUTH -#include - #include "vauth.h" #include "digest.h" -#include "../urldata.h" #include "../curlx/base64.h" -#include "../curl_hmac.h" #include "../curl_md5.h" #include "../curl_sha256.h" #include "../curl_sha512_256.h" -#include "../vtls/vtls.h" -#include "../curlx/warnless.h" #include "../curlx/strparse.h" #include "../rand.h" -/* The last #include files should be: */ -#include "../curl_memory.h" -#include "../memdebug.h" - #ifndef USE_WINDOWS_SSPI #define SESSION_ALGO 1 /* for algos with this bit set */ @@ -142,20 +132,20 @@ bool Curl_auth_digest_get_pair(const char *str, char *value, char *content, #ifndef USE_WINDOWS_SSPI /* Convert MD5 chunk to RFC2617 (section 3.1.3) -suitable ASCII string */ static void auth_digest_md5_to_ascii(unsigned char *source, /* 16 bytes */ - unsigned char *dest) /* 33 bytes */ + unsigned char *dest) /* 33 bytes */ { int i; for(i = 0; i < 16; i++) - curl_msnprintf((char *) &dest[i * 2], 3, "%02x", source[i]); + curl_msnprintf((char *)&dest[i * 2], 3, "%02x", source[i]); } /* Convert sha256 or SHA-512/256 chunk to RFC7616 -suitable ASCII string */ static void auth_digest_sha256_to_ascii(unsigned char *source, /* 32 bytes */ - unsigned char *dest) /* 65 bytes */ + unsigned char *dest) /* 65 bytes */ { int i; for(i = 0; i < 32; i++) - curl_msnprintf((char *) &dest[i * 2], 3, "%02x", source[i]); + curl_msnprintf((char *)&dest[i * 2], 3, "%02x", source[i]); } /* Perform quoted-string escaping as described in RFC2616 and its errata */ @@ -174,7 +164,7 @@ static char *auth_digest_string_quoted(const char *source) ++s; } - dest = malloc(n); + dest = curlx_malloc(n); if(dest) { char *d = dest; s = source; @@ -216,7 +206,7 @@ static bool auth_digest_get_key_value(const char *chlg, const char *key, if(curlx_str_cmp(&name, key)) { /* if this is our key, return the value */ if(curlx_strlen(&data) >= buflen) - /* doesn't fit */ + /* does not fit */ return FALSE; memcpy(buf, curlx_str(&data), curlx_strlen(&data)); buf[curlx_strlen(&data)] = 0; @@ -232,7 +222,7 @@ static bool auth_digest_get_key_value(const char *chlg, const char *key, return FALSE; } -static CURLcode auth_digest_get_qop_values(const char *options, int *value) +static void auth_digest_get_qop_values(const char *options, int *value) { struct Curl_str out; /* Initialise the output */ @@ -248,8 +238,6 @@ static CURLcode auth_digest_get_qop_values(const char *options, int *value) if(curlx_str_single(&options, ',')) break; } - - return CURLE_OK; } /* @@ -278,7 +266,7 @@ static CURLcode auth_decode_digest_md5_message(const struct bufref *chlgref, char *alg, size_t alen, char *qop, size_t qlen) { - const char *chlg = (const char *) Curl_bufref_ptr(chlgref); + const char *chlg = Curl_bufref_ptr(chlgref); /* Ensure we have a valid challenge message */ if(!Curl_bufref_len(chlgref)) @@ -377,9 +365,7 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, return CURLE_BAD_CONTENT_ENCODING; /* Get the qop-values from the qop-options */ - result = auth_digest_get_qop_values(qop_options, &qop_values); - if(result) - return result; + auth_digest_get_qop_values(qop_options, &qop_values); /* We only support auth quality-of-protection */ if(!(qop_values & DIGEST_QOP_VALUE_AUTH)) @@ -395,13 +381,13 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, if(!ctxt) return CURLE_OUT_OF_MEMORY; - Curl_MD5_update(ctxt, (const unsigned char *) userp, + Curl_MD5_update(ctxt, (const unsigned char *)userp, curlx_uztoui(strlen(userp))); - Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); - Curl_MD5_update(ctxt, (const unsigned char *) realm, + Curl_MD5_update(ctxt, (const unsigned char *)":", 1); + Curl_MD5_update(ctxt, (const unsigned char *)realm, curlx_uztoui(strlen(realm))); - Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); - Curl_MD5_update(ctxt, (const unsigned char *) passwdp, + Curl_MD5_update(ctxt, (const unsigned char *)":", 1); + Curl_MD5_update(ctxt, (const unsigned char *)passwdp, curlx_uztoui(strlen(passwdp))); Curl_MD5_final(ctxt, digest); @@ -409,12 +395,12 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, if(!ctxt) return CURLE_OUT_OF_MEMORY; - Curl_MD5_update(ctxt, (const unsigned char *) digest, MD5_DIGEST_LEN); - Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); - Curl_MD5_update(ctxt, (const unsigned char *) nonce, + Curl_MD5_update(ctxt, (const unsigned char *)digest, MD5_DIGEST_LEN); + Curl_MD5_update(ctxt, (const unsigned char *)":", 1); + Curl_MD5_update(ctxt, (const unsigned char *)nonce, curlx_uztoui(strlen(nonce))); - Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); - Curl_MD5_update(ctxt, (const unsigned char *) cnonce, + Curl_MD5_update(ctxt, (const unsigned char *)":", 1); + Curl_MD5_update(ctxt, (const unsigned char *)cnonce, curlx_uztoui(strlen(cnonce))); Curl_MD5_final(ctxt, digest); @@ -430,15 +416,15 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, /* Calculate H(A2) */ ctxt = Curl_MD5_init(&Curl_DIGEST_MD5); if(!ctxt) { - free(spn); + curlx_free(spn); return CURLE_OUT_OF_MEMORY; } - Curl_MD5_update(ctxt, (const unsigned char *) method, + Curl_MD5_update(ctxt, (const unsigned char *)method, curlx_uztoui(strlen(method))); - Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); - Curl_MD5_update(ctxt, (const unsigned char *) spn, + Curl_MD5_update(ctxt, (const unsigned char *)":", 1); + Curl_MD5_update(ctxt, (const unsigned char *)spn, curlx_uztoui(strlen(spn))); Curl_MD5_final(ctxt, digest); @@ -448,28 +434,28 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, /* Now calculate the response hash */ ctxt = Curl_MD5_init(&Curl_DIGEST_MD5); if(!ctxt) { - free(spn); + curlx_free(spn); return CURLE_OUT_OF_MEMORY; } - Curl_MD5_update(ctxt, (const unsigned char *) HA1_hex, 2 * MD5_DIGEST_LEN); - Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); - Curl_MD5_update(ctxt, (const unsigned char *) nonce, + Curl_MD5_update(ctxt, (const unsigned char *)HA1_hex, 2 * MD5_DIGEST_LEN); + Curl_MD5_update(ctxt, (const unsigned char *)":", 1); + Curl_MD5_update(ctxt, (const unsigned char *)nonce, curlx_uztoui(strlen(nonce))); - Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *)":", 1); - Curl_MD5_update(ctxt, (const unsigned char *) nonceCount, + Curl_MD5_update(ctxt, (const unsigned char *)nonceCount, curlx_uztoui(strlen(nonceCount))); - Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); - Curl_MD5_update(ctxt, (const unsigned char *) cnonce, + Curl_MD5_update(ctxt, (const unsigned char *)":", 1); + Curl_MD5_update(ctxt, (const unsigned char *)cnonce, curlx_uztoui(strlen(cnonce))); - Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); - Curl_MD5_update(ctxt, (const unsigned char *) qop, + Curl_MD5_update(ctxt, (const unsigned char *)":", 1); + Curl_MD5_update(ctxt, (const unsigned char *)qop, curlx_uztoui(strlen(qop))); - Curl_MD5_update(ctxt, (const unsigned char *) ":", 1); + Curl_MD5_update(ctxt, (const unsigned char *)":", 1); - Curl_MD5_update(ctxt, (const unsigned char *) HA2_hex, 2 * MD5_DIGEST_LEN); + Curl_MD5_update(ctxt, (const unsigned char *)HA2_hex, 2 * MD5_DIGEST_LEN); Curl_MD5_final(ctxt, digest); for(i = 0; i < MD5_DIGEST_LEN; i++) @@ -481,7 +467,7 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, "response=%s,qop=%s", userp, realm, nonce, cnonce, nonceCount, spn, resp_hash_hex, qop); - free(spn); + curlx_free(spn); if(!response) return CURLE_OUT_OF_MEMORY; @@ -526,8 +512,8 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg, /* Extract a value=content pair */ if(Curl_auth_digest_get_pair(chlg, value, content, &chlg)) { if(curl_strequal(value, "nonce")) { - free(digest->nonce); - digest->nonce = strdup(content); + curlx_free(digest->nonce); + digest->nonce = curlx_strdup(content); if(!digest->nonce) return CURLE_OUT_OF_MEMORY; } @@ -538,14 +524,14 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg, } } else if(curl_strequal(value, "realm")) { - free(digest->realm); - digest->realm = strdup(content); + curlx_free(digest->realm); + digest->realm = curlx_strdup(content); if(!digest->realm) return CURLE_OUT_OF_MEMORY; } else if(curl_strequal(value, "opaque")) { - free(digest->opaque); - digest->opaque = strdup(content); + curlx_free(digest->opaque); + digest->opaque = curlx_strdup(content); if(!digest->opaque) return CURLE_OUT_OF_MEMORY; } @@ -561,7 +547,7 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg, if(curlx_str_casecompare(&out, DIGEST_QOP_VALUE_STRING_AUTH)) foundAuth = TRUE; else if(curlx_str_casecompare(&out, - DIGEST_QOP_VALUE_STRING_AUTH_INT)) + DIGEST_QOP_VALUE_STRING_AUTH_INT)) foundAuthInt = TRUE; if(curlx_str_single(&token, ',')) break; @@ -571,21 +557,21 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg, /* Select only auth or auth-int. Otherwise, ignore */ if(foundAuth) { - free(digest->qop); - digest->qop = strdup(DIGEST_QOP_VALUE_STRING_AUTH); + curlx_free(digest->qop); + digest->qop = curlx_strdup(DIGEST_QOP_VALUE_STRING_AUTH); if(!digest->qop) return CURLE_OUT_OF_MEMORY; } else if(foundAuthInt) { - free(digest->qop); - digest->qop = strdup(DIGEST_QOP_VALUE_STRING_AUTH_INT); + curlx_free(digest->qop); + digest->qop = curlx_strdup(DIGEST_QOP_VALUE_STRING_AUTH_INT); if(!digest->qop) return CURLE_OUT_OF_MEMORY; } } else if(curl_strequal(value, "algorithm")) { - free(digest->algorithm); - digest->algorithm = strdup(content); + curlx_free(digest->algorithm); + digest->algorithm = curlx_strdup(content); if(!digest->algorithm) return CURLE_OUT_OF_MEMORY; @@ -714,7 +700,7 @@ static CURLcode auth_create_digest_http_message( if(result) return result; - result = curlx_base64_encode(cnoncebuf, sizeof(cnoncebuf), + result = curlx_base64_encode((uint8_t *)cnoncebuf, sizeof(cnoncebuf), &cnonce, &cnonce_sz); if(result) return result; @@ -728,8 +714,8 @@ static CURLcode auth_create_digest_http_message( if(!hashthis) return CURLE_OUT_OF_MEMORY; - result = hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis)); - free(hashthis); + result = hash(hashbuf, (unsigned char *)hashthis, strlen(hashthis)); + curlx_free(hashthis); if(result) return result; convert_to_ascii(hashbuf, (unsigned char *)userh); @@ -751,8 +737,8 @@ static CURLcode auth_create_digest_http_message( if(!hashthis) return CURLE_OUT_OF_MEMORY; - result = hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis)); - free(hashthis); + result = hash(hashbuf, (unsigned char *)hashthis, strlen(hashthis)); + curlx_free(hashthis); if(result) return result; convert_to_ascii(hashbuf, ha1); @@ -763,8 +749,8 @@ static CURLcode auth_create_digest_http_message( if(!tmp) return CURLE_OUT_OF_MEMORY; - result = hash(hashbuf, (unsigned char *) tmp, strlen(tmp)); - free(tmp); + result = hash(hashbuf, (unsigned char *)tmp, strlen(tmp)); + curlx_free(tmp); if(result) return result; convert_to_ascii(hashbuf, ha1); @@ -794,21 +780,21 @@ static CURLcode auth_create_digest_http_message( result = hash(hashbuf, (const unsigned char *)"", 0); if(result) { - free(hashthis); + curlx_free(hashthis); return result; } convert_to_ascii(hashbuf, (unsigned char *)hashed); hashthis2 = curl_maprintf("%s:%s", hashthis, hashed); - free(hashthis); + curlx_free(hashthis); hashthis = hashthis2; } if(!hashthis) return CURLE_OUT_OF_MEMORY; - result = hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis)); - free(hashthis); + result = hash(hashbuf, (unsigned char *)hashthis, strlen(hashthis)); + curlx_free(hashthis); if(result) return result; convert_to_ascii(hashbuf, ha2); @@ -824,8 +810,8 @@ static CURLcode auth_create_digest_http_message( if(!hashthis) return CURLE_OUT_OF_MEMORY; - result = hash(hashbuf, (unsigned char *) hashthis, strlen(hashthis)); - free(hashthis); + result = hash(hashbuf, (unsigned char *)hashthis, strlen(hashthis)); + curlx_free(hashthis); if(result) return result; convert_to_ascii(hashbuf, request_digest); @@ -849,18 +835,18 @@ static CURLcode auth_create_digest_http_message( if(digest->realm) realm_quoted = auth_digest_string_quoted(digest->realm); else { - realm_quoted = malloc(1); + realm_quoted = curlx_malloc(1); if(realm_quoted) realm_quoted[0] = 0; } if(!realm_quoted) { - free(userp_quoted); + curlx_free(userp_quoted); return CURLE_OUT_OF_MEMORY; } nonce_quoted = auth_digest_string_quoted(digest->nonce); if(!nonce_quoted) { - free(realm_quoted); - free(userp_quoted); + curlx_free(realm_quoted); + curlx_free(userp_quoted); return CURLE_OUT_OF_MEMORY; } @@ -897,9 +883,9 @@ static CURLcode auth_create_digest_http_message( uripath, request_digest); } - free(nonce_quoted); - free(realm_quoted); - free(userp_quoted); + curlx_free(nonce_quoted); + curlx_free(realm_quoted); + curlx_free(userp_quoted); if(!response) return CURLE_OUT_OF_MEMORY; @@ -909,12 +895,12 @@ static CURLcode auth_create_digest_http_message( /* Append the opaque */ opaque_quoted = auth_digest_string_quoted(digest->opaque); if(!opaque_quoted) { - free(response); + curlx_free(response); return CURLE_OUT_OF_MEMORY; } tmp = curl_maprintf("%s, opaque=\"%s\"", response, opaque_quoted); - free(response); - free(opaque_quoted); + curlx_free(response); + curlx_free(opaque_quoted); if(!tmp) return CURLE_OUT_OF_MEMORY; @@ -924,7 +910,7 @@ static CURLcode auth_create_digest_http_message( if(digest->algorithm) { /* Append the algorithm */ tmp = curl_maprintf("%s, algorithm=%s", response, digest->algorithm); - free(response); + curlx_free(response); if(!tmp) return CURLE_OUT_OF_MEMORY; @@ -934,7 +920,7 @@ static CURLcode auth_create_digest_http_message( if(digest->userhash) { /* Append the userhash */ tmp = curl_maprintf("%s, userhash=true", response); - free(response); + curlx_free(response); if(!tmp) return CURLE_OUT_OF_MEMORY; @@ -1023,9 +1009,9 @@ void Curl_auth_digest_cleanup(struct digestdata *digest) digest->nc = 0; digest->algo = ALGO_MD5; /* default algorithm */ - digest->stale = FALSE; /* default means normal, not stale */ + digest->stale = FALSE; /* default means normal, not stale */ digest->userhash = FALSE; } -#endif /* !USE_WINDOWS_SSPI */ +#endif /* !USE_WINDOWS_SSPI */ -#endif /* !CURL_DISABLE_DIGEST_AUTH */ +#endif /* !CURL_DISABLE_DIGEST_AUTH */ diff --git a/lib/vauth/digest.h b/lib/vauth/digest.h index 99ce1f913892..63f388bf46b0 100644 --- a/lib/vauth/digest.h +++ b/lib/vauth/digest.h @@ -24,7 +24,7 @@ * ***************************************************************************/ -#include +#include "../curl_setup.h" #ifndef CURL_DISABLE_DIGEST_AUTH diff --git a/lib/vauth/digest_sspi.c b/lib/vauth/digest_sspi.c index 5bf37705653a..bc681d13dc88 100644 --- a/lib/vauth/digest_sspi.c +++ b/lib/vauth/digest_sspi.c @@ -29,31 +29,23 @@ #if defined(USE_WINDOWS_SSPI) && !defined(CURL_DISABLE_DIGEST_AUTH) -#include - #include "vauth.h" #include "digest.h" -#include "../urldata.h" -#include "../curlx/warnless.h" #include "../curlx/multibyte.h" -#include "../sendf.h" +#include "../curl_trc.h" #include "../strdup.h" #include "../strcase.h" #include "../strerror.h" -/* The last #include files should be: */ -#include "../curl_memory.h" -#include "../memdebug.h" - /* -* Curl_auth_is_digest_supported() -* -* This is used to evaluate if DIGEST is supported. -* -* Parameters: None -* -* Returns TRUE if DIGEST is supported by Windows SSPI. -*/ + * Curl_auth_is_digest_supported() + * + * This is used to evaluate if DIGEST is supported. + * + * Parameters: None + * + * Returns TRUE if DIGEST is supported by Windows SSPI. + */ bool Curl_auth_is_digest_supported(void) { PSecPkgInfo SecurityPackage; @@ -135,14 +127,14 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, Curl_pSecFn->FreeContextBuffer(SecurityPackage); /* Allocate our response buffer */ - output_token = malloc(token_max); + output_token = curlx_malloc(token_max); if(!output_token) return CURLE_OUT_OF_MEMORY; /* Generate our SPN */ spn = Curl_auth_build_spn(service, data->conn->host.name, NULL); if(!spn) { - free(output_token); + curlx_free(output_token); return CURLE_OUT_OF_MEMORY; } @@ -150,8 +142,8 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, /* Populate our identity structure */ result = Curl_create_sspi_identity(userp, passwdp, &identity); if(result) { - free(spn); - free(output_token); + curlx_free(spn); + curlx_free(output_token); return result; } @@ -171,8 +163,8 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, if(status != SEC_E_OK) { Curl_sspi_free_identity(p_identity); - free(spn); - free(output_token); + curlx_free(spn); + curlx_free(output_token); return CURLE_LOGIN_DENIED; } @@ -208,8 +200,8 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, Curl_pSecFn->FreeCredentialsHandle(&credentials); Curl_sspi_free_identity(p_identity); - free(spn); - free(output_token); + curlx_free(spn); + curlx_free(output_token); if(status == SEC_E_INSUFFICIENT_MEMORY) return CURLE_OUT_OF_MEMORY; @@ -233,7 +225,7 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data, Curl_sspi_free_identity(p_identity); /* Free the SPN */ - free(spn); + curlx_free(spn); return result; } @@ -276,18 +268,18 @@ CURLcode Curl_override_sspi_http_realm(const char *chlg, if(!domain.tchar_ptr) return CURLE_OUT_OF_MEMORY; - dup_domain.tchar_ptr = Curl_tcsdup(domain.tchar_ptr); + dup_domain.tchar_ptr = curlx_tcsdup(domain.tchar_ptr); if(!dup_domain.tchar_ptr) { - curlx_unicodefree(domain.tchar_ptr); + curlx_free(domain.tchar_ptr); return CURLE_OUT_OF_MEMORY; } - free(identity->Domain); + curlx_free(identity->Domain); identity->Domain = dup_domain.tbyte_ptr; identity->DomainLength = curlx_uztoul(_tcslen(dup_domain.tchar_ptr)); dup_domain.tchar_ptr = NULL; - curlx_unicodefree(domain.tchar_ptr); + curlx_free(domain.tchar_ptr); } else { /* Unknown specifier, ignore it! */ @@ -429,7 +421,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, /* Allocate the output buffer according to the max token size as indicated by the security package */ - output_token = malloc(token_max); + output_token = curlx_malloc(token_max); if(!output_token) { return CURLE_OUT_OF_MEMORY; } @@ -457,10 +449,10 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, chlg_buf[0].cbBuffer = 0; chlg_buf[1].BufferType = SECBUFFER_PKG_PARAMS; chlg_buf[1].pvBuffer = CURL_UNCONST(request); - chlg_buf[1].cbBuffer = curlx_uztoul(strlen((const char *) request)); + chlg_buf[1].cbBuffer = curlx_uztoul(strlen((const char *)request)); chlg_buf[2].BufferType = SECBUFFER_PKG_PARAMS; chlg_buf[2].pvBuffer = CURL_UNCONST(uripath); - chlg_buf[2].cbBuffer = curlx_uztoul(strlen((const char *) uripath)); + chlg_buf[2].cbBuffer = curlx_uztoul(strlen((const char *)uripath)); chlg_buf[3].BufferType = SECBUFFER_PKG_PARAMS; chlg_buf[3].pvBuffer = NULL; chlg_buf[3].cbBuffer = 0; @@ -495,14 +487,15 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, if(userp && *userp) { /* Populate our identity structure */ if(Curl_create_sspi_identity(userp, passwdp, &identity)) { - free(output_token); + curlx_free(output_token); return CURLE_OUT_OF_MEMORY; } /* Populate our identity domain */ - if(Curl_override_sspi_http_realm((const char *) digest->input_token, + if(Curl_override_sspi_http_realm((const char *)digest->input_token, &identity)) { - free(output_token); + Curl_sspi_free_identity(&identity); + curlx_free(output_token); return CURLE_OUT_OF_MEMORY; } @@ -514,20 +507,20 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, p_identity = NULL; if(userp) { - digest->user = strdup(userp); + digest->user = curlx_strdup(userp); if(!digest->user) { - free(output_token); + curlx_free(output_token); Curl_sspi_free_identity(p_identity); return CURLE_OUT_OF_MEMORY; } } if(passwdp) { - digest->passwd = strdup(passwdp); + digest->passwd = curlx_strdup(passwdp); if(!digest->passwd) { - free(output_token); + curlx_free(output_token); Curl_sspi_free_identity(p_identity); Curl_safefree(digest->user); return CURLE_OUT_OF_MEMORY; @@ -542,7 +535,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, &credentials, NULL); if(status != SEC_E_OK) { Curl_sspi_free_identity(p_identity); - free(output_token); + curlx_free(output_token); return CURLE_LOGIN_DENIED; } @@ -556,7 +549,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, chlg_buf[0].cbBuffer = curlx_uztoul(digest->input_token_len); chlg_buf[1].BufferType = SECBUFFER_PKG_PARAMS; chlg_buf[1].pvBuffer = CURL_UNCONST(request); - chlg_buf[1].cbBuffer = curlx_uztoul(strlen((const char *) request)); + chlg_buf[1].cbBuffer = curlx_uztoul(strlen((const char *)request)); chlg_buf[2].BufferType = SECBUFFER_PKG_PARAMS; chlg_buf[2].pvBuffer = NULL; chlg_buf[2].cbBuffer = 0; @@ -569,22 +562,23 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, resp_buf.pvBuffer = output_token; resp_buf.cbBuffer = curlx_uztoul(token_max); - spn = curlx_convert_UTF8_to_tchar((const char *) uripath); + spn = curlx_convert_UTF8_to_tchar((const char *)uripath); if(!spn) { Curl_pSecFn->FreeCredentialsHandle(&credentials); Curl_sspi_free_identity(p_identity); - free(output_token); + curlx_free(output_token); return CURLE_OUT_OF_MEMORY; } /* Allocate our new context handle */ - digest->http_context = calloc(1, sizeof(CtxtHandle)); + digest->http_context = curlx_calloc(1, sizeof(CtxtHandle)); if(!digest->http_context) { - curlx_unicodefree(spn); + Curl_pSecFn->FreeCredentialsHandle(&credentials); + curlx_free(spn); Curl_sspi_free_identity(p_identity); - free(output_token); + curlx_free(output_token); return CURLE_OUT_OF_MEMORY; } @@ -595,7 +589,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, &chlg_desc, 0, digest->http_context, &resp_desc, &attrs, NULL); - curlx_unicodefree(spn); + curlx_free(spn); if(status == SEC_I_COMPLETE_NEEDED || status == SEC_I_COMPLETE_AND_CONTINUE) @@ -608,7 +602,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, Curl_pSecFn->FreeCredentialsHandle(&credentials); Curl_sspi_free_identity(p_identity); - free(output_token); + curlx_free(output_token); Curl_safefree(digest->http_context); @@ -629,24 +623,15 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data, Curl_sspi_free_identity(p_identity); } - resp = malloc(output_token_len + 1); + resp = Curl_memdup0((const char *)output_token, output_token_len); + curlx_free(output_token); if(!resp) { - free(output_token); - return CURLE_OUT_OF_MEMORY; } - /* Copy the generated response */ - memcpy(resp, output_token, output_token_len); - resp[output_token_len] = 0; - /* Return the response */ *outptr = resp; *outlen = output_token_len; - - /* Free the response buffer */ - free(output_token); - return CURLE_OK; } diff --git a/lib/vauth/gsasl.c b/lib/vauth/gsasl.c index 8fbb62af80d6..2f82254608db 100644 --- a/lib/vauth/gsasl.c +++ b/lib/vauth/gsasl.c @@ -28,18 +28,11 @@ #ifdef USE_GSASL -#include - #include "vauth.h" -#include "../urldata.h" -#include "../sendf.h" +#include "../curl_trc.h" #include -/* The last 2 #include files should be in this order */ -#include "../curl_memory.h" -#include "../memdebug.h" - bool Curl_auth_gsasl_is_supported(struct Curl_easy *data, const char *mech, struct gsasldata *gsasl) @@ -48,7 +41,7 @@ bool Curl_auth_gsasl_is_supported(struct Curl_easy *data, res = gsasl_init(&gsasl->ctx); if(res != GSASL_OK) { - failf(data, "gsasl init: %s\n", gsasl_strerror(res)); + failf(data, "gsasl init: %s", gsasl_strerror(res)); return FALSE; } @@ -73,7 +66,7 @@ CURLcode Curl_auth_gsasl_start(struct Curl_easy *data, gsasl_property_set(gsasl->client, GSASL_AUTHID, userp); #if GSASL_VERSION_NUMBER >= 0x010b00 if(res != GSASL_OK) { - failf(data, "setting AUTHID failed: %s\n", gsasl_strerror(res)); + failf(data, "setting AUTHID failed: %s", gsasl_strerror(res)); return CURLE_OUT_OF_MEMORY; } #endif @@ -84,7 +77,7 @@ CURLcode Curl_auth_gsasl_start(struct Curl_easy *data, gsasl_property_set(gsasl->client, GSASL_PASSWORD, passwdp); #if GSASL_VERSION_NUMBER >= 0x010b00 if(res != GSASL_OK) { - failf(data, "setting PASSWORD failed: %s\n", gsasl_strerror(res)); + failf(data, "setting PASSWORD failed: %s", gsasl_strerror(res)); return CURLE_OUT_OF_MEMORY; } #endif @@ -103,11 +96,10 @@ CURLcode Curl_auth_gsasl_token(struct Curl_easy *data, char *response; size_t outlen; - res = gsasl_step(gsasl->client, - (const char *) Curl_bufref_ptr(chlg), Curl_bufref_len(chlg), + res = gsasl_step(gsasl->client, Curl_bufref_ptr(chlg), Curl_bufref_len(chlg), &response, &outlen); if(res != GSASL_OK && res != GSASL_NEEDS_MORE) { - failf(data, "GSASL step: %s\n", gsasl_strerror(res)); + failf(data, "GSASL step: %s", gsasl_strerror(res)); return CURLE_BAD_CONTENT_ENCODING; } diff --git a/lib/vauth/krb5_gssapi.c b/lib/vauth/krb5_gssapi.c index a414d0a35961..64797190ce30 100644 --- a/lib/vauth/krb5_gssapi.c +++ b/lib/vauth/krb5_gssapi.c @@ -29,17 +29,10 @@ #if defined(HAVE_GSSAPI) && defined(USE_KERBEROS5) -#include - #include "vauth.h" #include "../curl_sasl.h" -#include "../urldata.h" #include "../curl_gssapi.h" -#include "../sendf.h" - -/* The last #include files should be: */ -#include "../curl_memory.h" -#include "../memdebug.h" +#include "../curl_trc.h" #if defined(__GNUC__) && defined(__APPLE__) #pragma GCC diagnostic push @@ -120,12 +113,12 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, Curl_gss_log_error(data, "gss_import_name() failed: ", major_status, minor_status); - free(spn); + curlx_free(spn); return CURLE_AUTH_ERROR; } - free(spn); + curlx_free(spn); } if(chlg) { @@ -159,11 +152,11 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, } if(output_token.value && output_token.length) { - result = Curl_bufref_memdup(out, output_token.value, output_token.length); + result = Curl_bufref_memdup0(out, output_token.value, output_token.length); gss_release_buffer(&unused_status, &output_token); } else - Curl_bufref_set(out, mutual_auth ? "": NULL, 0, NULL); + Curl_bufref_set(out, mutual_auth ? "" : NULL, 0, NULL); return result; } @@ -258,7 +251,7 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, messagelen = 4; if(authzid) messagelen += strlen(authzid); - message = malloc(messagelen); + message = curlx_malloc(messagelen); if(!message) return CURLE_OUT_OF_MEMORY; @@ -285,17 +278,17 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, if(GSS_ERROR(major_status)) { Curl_gss_log_error(data, "gss_wrap() failed: ", major_status, minor_status); - free(message); + curlx_free(message); return CURLE_AUTH_ERROR; } /* Return the response. */ - result = Curl_bufref_memdup(out, output_token.value, output_token.length); + result = Curl_bufref_memdup0(out, output_token.value, output_token.length); /* Free the output buffer */ gss_release_buffer(&unused_status, &output_token); /* Free the message buffer */ - free(message); + curlx_free(message); return result; } diff --git a/lib/vauth/krb5_sspi.c b/lib/vauth/krb5_sspi.c index c1953e114569..d88ee79bdec9 100644 --- a/lib/vauth/krb5_sspi.c +++ b/lib/vauth/krb5_sspi.c @@ -28,17 +28,8 @@ #if defined(USE_WINDOWS_SSPI) && defined(USE_KERBEROS5) -#include - #include "vauth.h" -#include "../urldata.h" -#include "../curlx/warnless.h" -#include "../curlx/multibyte.h" -#include "../sendf.h" - -/* The last #include files should be: */ -#include "../curl_memory.h" -#include "../memdebug.h" +#include "../curl_trc.h" /* * Curl_auth_is_gssapi_supported() @@ -131,7 +122,7 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, Curl_pSecFn->FreeContextBuffer(SecurityPackage); /* Allocate our response buffer */ - krb5->output_token = malloc(krb5->token_max); + krb5->output_token = curlx_malloc(krb5->token_max); if(!krb5->output_token) return CURLE_OUT_OF_MEMORY; } @@ -152,7 +143,7 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, krb5->p_identity = NULL; /* Allocate our credentials handle */ - krb5->credentials = calloc(1, sizeof(CredHandle)); + krb5->credentials = curlx_calloc(1, sizeof(CredHandle)); if(!krb5->credentials) return CURLE_OUT_OF_MEMORY; @@ -166,7 +157,7 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, return CURLE_LOGIN_DENIED; /* Allocate our new context handle */ - krb5->context = calloc(1, sizeof(CtxtHandle)); + krb5->context = curlx_calloc(1, sizeof(CtxtHandle)); if(!krb5->context) return CURLE_OUT_OF_MEMORY; } @@ -218,7 +209,7 @@ CURLcode Curl_auth_create_gssapi_user_message(struct Curl_easy *data, } if(resp_buf.cbBuffer) { - result = Curl_bufref_memdup(out, resp_buf.pvBuffer, resp_buf.cbBuffer); + result = Curl_bufref_memdup0(out, resp_buf.pvBuffer, resp_buf.cbBuffer); } else if(mutual_auth) Curl_bufref_set(out, "", 0, NULL); @@ -250,6 +241,7 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, struct kerberos5data *krb5, struct bufref *out) { + CURLcode result = CURLE_OK; size_t offset = 0; size_t messagelen = 0; size_t appdatalen = 0; @@ -281,8 +273,7 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, /* Get our response size information */ status = Curl_pSecFn->QueryContextAttributes(krb5->context, - SECPKG_ATTR_SIZES, - &sizes); + SECPKG_ATTR_SIZES, &sizes); if(status == SEC_E_INSUFFICIENT_MEMORY) return CURLE_OUT_OF_MEMORY; @@ -339,7 +330,7 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, } /* Allocate the trailer */ - trailer = malloc(sizes.cbSecurityTrailer); + trailer = curlx_malloc(sizes.cbSecurityTrailer); if(!trailer) return CURLE_OUT_OF_MEMORY; @@ -347,11 +338,10 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, messagelen = 4; if(authzid) messagelen += strlen(authzid); - message = malloc(messagelen); + message = curlx_malloc(messagelen); if(!message) { - free(trailer); - - return CURLE_OUT_OF_MEMORY; + result = CURLE_OUT_OF_MEMORY; + goto out; } /* Populate the message with the security layer and client supported receive @@ -367,12 +357,10 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, memcpy(message + 4, authzid, messagelen - 4); /* Allocate the padding */ - padding = malloc(sizes.cbBlockSize); + padding = curlx_malloc(sizes.cbBlockSize); if(!padding) { - free(message); - free(trailer); - - return CURLE_OUT_OF_MEMORY; + result = CURLE_OUT_OF_MEMORY; + goto out; } /* Setup the "authentication data" security buffer */ @@ -393,26 +381,20 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, status = Curl_pSecFn->EncryptMessage(krb5->context, KERB_WRAP_NO_ENCRYPT, &wrap_desc, 0); if(status != SEC_E_OK) { - free(padding); - free(message); - free(trailer); - if(status == SEC_E_INSUFFICIENT_MEMORY) - return CURLE_OUT_OF_MEMORY; - - return CURLE_AUTH_ERROR; + result = CURLE_OUT_OF_MEMORY; + else + result = CURLE_AUTH_ERROR; + goto out; } /* Allocate the encryption (wrap) buffer */ appdatalen = wrap_buf[0].cbBuffer + wrap_buf[1].cbBuffer + wrap_buf[2].cbBuffer; - appdata = malloc(appdatalen); + appdata = curlx_malloc(appdatalen); if(!appdata) { - free(padding); - free(message); - free(trailer); - - return CURLE_OUT_OF_MEMORY; + result = CURLE_OUT_OF_MEMORY; + goto out; } /* Populate the encryption buffer */ @@ -422,10 +404,14 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data, offset += wrap_buf[1].cbBuffer; memcpy(appdata + offset, wrap_buf[2].pvBuffer, wrap_buf[2].cbBuffer); +out: /* Free all of our local buffers */ - free(padding); - free(message); - free(trailer); + curlx_free(padding); + curlx_free(message); + curlx_free(trailer); + + if(result) + return result; /* Return the response. */ Curl_bufref_set(out, appdata, appdatalen, curl_free); @@ -447,14 +433,14 @@ void Curl_auth_cleanup_gssapi(struct kerberos5data *krb5) /* Free our security context */ if(krb5->context) { Curl_pSecFn->DeleteSecurityContext(krb5->context); - free(krb5->context); + curlx_free(krb5->context); krb5->context = NULL; } /* Free our credentials handle */ if(krb5->credentials) { Curl_pSecFn->FreeCredentialsHandle(krb5->credentials); - free(krb5->credentials); + curlx_free(krb5->credentials); krb5->credentials = NULL; } diff --git a/lib/vauth/ntlm.c b/lib/vauth/ntlm.c index 791fc87d1153..620f2a5c8452 100644 --- a/lib/vauth/ntlm.c +++ b/lib/vauth/ntlm.c @@ -35,25 +35,13 @@ #define DEBUG_ME 0 -#include "../urldata.h" -#include "../sendf.h" +#include "vauth.h" +#include "../curl_trc.h" #include "../curl_ntlm_core.h" -#include "../curl_gethostname.h" -#include "../curlx/multibyte.h" -#include "../curl_md5.h" -#include "../curlx/warnless.h" #include "../rand.h" -#include "../vtls/vtls.h" #include "../strdup.h" - -#include "vauth.h" #include "../curl_endian.h" -/* The last #include files should be: */ -#include "../curl_memory.h" -#include "../memdebug.h" - - /* NTLM buffer fixed size, large enough for long user + host + domain */ #define NTLM_BUFSIZE 1024 @@ -163,7 +151,7 @@ #define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50" #if DEBUG_ME -# define DEBUG_OUT(x) x +#define DEBUG_OUT(x) x static void ntlm_print_flags(FILE *handle, unsigned long flags) { if(flags & NTLMFLAG_NEGOTIATE_UNICODE) @@ -241,7 +229,7 @@ static void ntlm_print_hex(FILE *handle, const char *buf, size_t len) curl_mfprintf(stderr, "%02.2x", (unsigned int)*p++); } #else -# define DEBUG_OUT(x) Curl_nop_stmt +#define DEBUG_OUT(x) Curl_nop_stmt #endif /* @@ -264,7 +252,7 @@ static CURLcode ntlm_decode_type2_target(struct Curl_easy *data, { unsigned short target_info_len = 0; unsigned int target_info_offset = 0; - const unsigned char *type2 = Curl_bufref_ptr(type2ref); + const unsigned char *type2 = Curl_bufref_uptr(type2ref); size_t type2len = Curl_bufref_len(type2ref); #ifdef CURL_DISABLE_VERBOSE_STRINGS @@ -283,7 +271,7 @@ static CURLcode ntlm_decode_type2_target(struct Curl_easy *data, return CURLE_BAD_CONTENT_ENCODING; } - free(ntlm->target_info); /* replace any previous data */ + curlx_free(ntlm->target_info); /* replace any previous data */ ntlm->target_info = Curl_memdup(&type2[target_info_offset], target_info_len); if(!ntlm->target_info) @@ -364,7 +352,7 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, */ CURLcode result = CURLE_OK; - const unsigned char *type2 = Curl_bufref_ptr(type2ref); + const unsigned char *type2 = Curl_bufref_uptr(type2ref); size_t type2len = Curl_bufref_len(type2ref); #ifdef CURL_DISABLE_VERBOSE_STRINGS @@ -788,7 +776,8 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, /* ntresplen + size should not be risking an integer overflow here */ if(ntresplen + size > sizeof(ntlmbuf)) { failf(data, "incoming NTLM message too big"); - return CURLE_OUT_OF_MEMORY; + result = CURLE_TOO_LARGE; + goto error; } DEBUGASSERT(size == (size_t)ntrespoff); memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen); @@ -799,8 +788,6 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], ntresplen); }); - free(ntlmv2resp);/* Free the dynamic buffer allocated for NTLMv2 */ - DEBUG_OUT({ curl_mfprintf(stderr, "\n flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ", LONGQUARTET(ntlm->flags), ntlm->flags); @@ -811,8 +798,9 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, /* Make sure that the domain, user and host strings fit in the buffer before we copy them there. */ if(size + userlen + domlen + hostlen >= NTLM_BUFSIZE) { - failf(data, "user + domain + hostname too big"); - return CURLE_OUT_OF_MEMORY; + failf(data, "user + domain + hostname too big for NTLM"); + result = CURLE_TOO_LARGE; + goto error; } DEBUGASSERT(size == domoff); @@ -840,7 +828,10 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, size += hostlen; /* Return the binary blob. */ - result = Curl_bufref_memdup(out, ntlmbuf, size); + result = Curl_bufref_memdup0(out, ntlmbuf, size); + +error: + curlx_free(ntlmv2resp); /* Free the dynamic buffer allocated for NTLMv2 */ Curl_auth_cleanup_ntlm(ntlm); diff --git a/lib/vauth/ntlm_sspi.c b/lib/vauth/ntlm_sspi.c index 071617182e7e..3d6712766ebb 100644 --- a/lib/vauth/ntlm_sspi.c +++ b/lib/vauth/ntlm_sspi.c @@ -26,20 +26,11 @@ #if defined(USE_WINDOWS_SSPI) && defined(USE_NTLM) -#include - #include "vauth.h" -#include "../urldata.h" #include "../curl_ntlm_core.h" -#include "../curlx/warnless.h" -#include "../curlx/multibyte.h" -#include "../sendf.h" +#include "../curl_trc.h" #include "../strdup.h" -/* The last #include files should be: */ -#include "../curl_memory.h" -#include "../memdebug.h" - /* * Curl_auth_is_ntlm_supported() * @@ -117,7 +108,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, Curl_pSecFn->FreeContextBuffer(SecurityPackage); /* Allocate our output buffer */ - ntlm->output_token = malloc(ntlm->token_max); + ntlm->output_token = curlx_malloc(ntlm->token_max); if(!ntlm->output_token) return CURLE_OUT_OF_MEMORY; @@ -137,7 +128,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, ntlm->p_identity = NULL; /* Allocate our credentials handle */ - ntlm->credentials = calloc(1, sizeof(CredHandle)); + ntlm->credentials = curlx_calloc(1, sizeof(CredHandle)); if(!ntlm->credentials) return CURLE_OUT_OF_MEMORY; @@ -151,7 +142,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data, return CURLE_LOGIN_DENIED; /* Allocate our new context handle */ - ntlm->context = calloc(1, sizeof(CtxtHandle)); + ntlm->context = curlx_calloc(1, sizeof(CtxtHandle)); if(!ntlm->context) return CURLE_OUT_OF_MEMORY; @@ -215,7 +206,7 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, } /* Store the challenge for later use */ - ntlm->input_token = Curl_memdup0((const char *)Curl_bufref_ptr(type2), + ntlm->input_token = Curl_memdup0(Curl_bufref_ptr(type2), Curl_bufref_len(type2)); if(!ntlm->input_token) return CURLE_OUT_OF_MEMORY; @@ -225,7 +216,6 @@ CURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data, } /* -* Curl_auth_create_ntlm_type3_message() * Curl_auth_create_ntlm_type3_message() * * This is used to generate an already encoded NTLM type-3 message ready for @@ -271,12 +261,12 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, #ifdef SECPKG_ATTR_ENDPOINT_BINDINGS /* ssl context comes from schannel. - * When extended protection is used in IIS server, - * we have to pass a second SecBuffer to the SecBufferDesc - * otherwise IIS will not pass the authentication (401 response). - * Minimum supported version is Windows 7. - * https://learn.microsoft.com/security-updates/SecurityAdvisories/2009/973811 - */ + * When extended protection is used in IIS server, + * we have to pass a second SecBuffer to the SecBufferDesc + * otherwise IIS will not pass the authentication (401 response). + * Minimum supported version is Windows 7. + * https://learn.microsoft.com/security-updates/SecurityAdvisories/2009/973811 + */ if(ntlm->sslContext) { SEC_CHANNEL_BINDINGS channelBindings; SecPkgContext_Bindings pkgBindings; @@ -323,7 +313,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data, } /* Return the response. */ - result = Curl_bufref_memdup(out, ntlm->output_token, type_3_buf.cbBuffer); + result = Curl_bufref_memdup0(out, ntlm->output_token, type_3_buf.cbBuffer); Curl_auth_cleanup_ntlm(ntlm); return result; } @@ -343,14 +333,14 @@ void Curl_auth_cleanup_ntlm(struct ntlmdata *ntlm) /* Free our security context */ if(ntlm->context) { Curl_pSecFn->DeleteSecurityContext(ntlm->context); - free(ntlm->context); + curlx_free(ntlm->context); ntlm->context = NULL; } /* Free our credentials handle */ if(ntlm->credentials) { Curl_pSecFn->FreeCredentialsHandle(ntlm->credentials); - free(ntlm->credentials); + curlx_free(ntlm->credentials); ntlm->credentials = NULL; } diff --git a/lib/vauth/oauth2.c b/lib/vauth/oauth2.c index cf7addf53597..fc89cba49f44 100644 --- a/lib/vauth/oauth2.c +++ b/lib/vauth/oauth2.c @@ -27,18 +27,10 @@ #include "../curl_setup.h" #if !defined(CURL_DISABLE_IMAP) || !defined(CURL_DISABLE_SMTP) || \ - !defined(CURL_DISABLE_POP3) || \ + !defined(CURL_DISABLE_POP3) || \ (!defined(CURL_DISABLE_LDAP) && defined(USE_OPENLDAP)) -#include -#include "../urldata.h" - #include "vauth.h" -#include "../curlx/warnless.h" - -/* The last #include files should be: */ -#include "../curl_memory.h" -#include "../memdebug.h" /* * Curl_auth_create_oauth_bearer_message() diff --git a/lib/vauth/spnego_gssapi.c b/lib/vauth/spnego_gssapi.c index 4ed02a398ca3..08689fe5e0ae 100644 --- a/lib/vauth/spnego_gssapi.c +++ b/lib/vauth/spnego_gssapi.c @@ -28,19 +28,10 @@ #if defined(HAVE_GSSAPI) && defined(USE_SPNEGO) -#include - #include "vauth.h" -#include "../urldata.h" #include "../curlx/base64.h" #include "../curl_gssapi.h" -#include "../curlx/warnless.h" -#include "../curlx/multibyte.h" -#include "../sendf.h" - -/* The last #include files should be: */ -#include "../curl_memory.h" -#include "../memdebug.h" +#include "../curl_trc.h" #if defined(__GNUC__) && defined(__APPLE__) #pragma GCC diagnostic push @@ -96,7 +87,9 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data, gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; gss_channel_bindings_t chan_bindings = GSS_C_NO_CHANNEL_BINDINGS; +#ifdef GSS_C_CHANNEL_BOUND_FLAG struct gss_channel_bindings_struct chan; +#endif (void)user; (void)password; @@ -129,12 +122,12 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data, Curl_gss_log_error(data, "gss_import_name() failed: ", major_status, minor_status); - free(spn); + curlx_free(spn); return CURLE_AUTH_ERROR; } - free(spn); + curlx_free(spn); } if(chlg64 && *chlg64) { @@ -157,12 +150,14 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data, } /* Set channel binding data if available */ +#ifdef GSS_C_CHANNEL_BOUND_FLAG if(curlx_dyn_len(&nego->channel_binding_data)) { memset(&chan, 0, sizeof(struct gss_channel_bindings_struct)); chan.application_data.length = curlx_dyn_len(&nego->channel_binding_data); chan.application_data.value = curlx_dyn_ptr(&nego->channel_binding_data); chan_bindings = &chan; } +#endif /* Generate our challenge-response message */ major_status = Curl_gss_init_sec_context(data, diff --git a/lib/vauth/spnego_sspi.c b/lib/vauth/spnego_sspi.c index 935468f3a65e..280753e39677 100644 --- a/lib/vauth/spnego_sspi.c +++ b/lib/vauth/spnego_sspi.c @@ -28,20 +28,11 @@ #if defined(USE_WINDOWS_SSPI) && defined(USE_SPNEGO) -#include - #include "vauth.h" -#include "../urldata.h" #include "../curlx/base64.h" -#include "../curlx/warnless.h" -#include "../curlx/multibyte.h" -#include "../sendf.h" +#include "../curl_trc.h" #include "../strerror.h" -/* The last #include files should be: */ -#include "../curl_memory.h" -#include "../memdebug.h" - /* * Curl_auth_is_spnego_supported() * @@ -66,7 +57,6 @@ bool Curl_auth_is_spnego_supported(void) Curl_pSecFn->FreeContextBuffer(SecurityPackage); } - return status == SEC_E_OK; } @@ -141,10 +131,10 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data, Curl_pSecFn->FreeContextBuffer(SecurityPackage); /* Allocate our output buffer */ - nego->output_token = malloc(nego->token_max); + nego->output_token = curlx_malloc(nego->token_max); if(!nego->output_token) return CURLE_OUT_OF_MEMORY; - } + } if(!nego->credentials) { /* Do we have credentials to use or are we using single sign-on? */ @@ -162,7 +152,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data, nego->p_identity = NULL; /* Allocate our credentials handle */ - nego->credentials = calloc(1, sizeof(CredHandle)); + nego->credentials = curlx_calloc(1, sizeof(CredHandle)); if(!nego->credentials) return CURLE_OUT_OF_MEMORY; @@ -176,7 +166,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data, return CURLE_AUTH_ERROR; /* Allocate our new context handle */ - nego->context = calloc(1, sizeof(CtxtHandle)); + nego->context = curlx_calloc(1, sizeof(CtxtHandle)); if(!nego->context) return CURLE_OUT_OF_MEMORY; } @@ -205,12 +195,12 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data, #ifdef SECPKG_ATTR_ENDPOINT_BINDINGS /* ssl context comes from Schannel. - * When extended protection is used in IIS server, - * we have to pass a second SecBuffer to the SecBufferDesc - * otherwise IIS will not pass the authentication (401 response). - * Minimum supported version is Windows 7. - * https://learn.microsoft.com/security-updates/SecurityAdvisories/2009/973811 - */ + * When extended protection is used in IIS server, + * we have to pass a second SecBuffer to the SecBufferDesc + * otherwise IIS will not pass the authentication (401 response). + * Minimum supported version is Windows 7. + * https://learn.microsoft.com/security-updates/SecurityAdvisories/2009/973811 + */ if(nego->sslContext) { SEC_CHANNEL_BINDINGS channelBindings; SecPkgContext_Bindings pkgBindings; @@ -249,7 +239,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data, &resp_desc, &attrs, NULL); /* Free the decoded challenge as it is not required anymore */ - free(chlg); + curlx_free(chlg); if(GSS_ERROR(nego->status)) { char buffer[STRERROR_LEN]; @@ -302,11 +292,11 @@ CURLcode Curl_auth_create_spnego_message(struct negotiatedata *nego, char **outptr, size_t *outlen) { /* Base64 encode the already generated response */ - CURLcode result = curlx_base64_encode((const char *)nego->output_token, + CURLcode result = curlx_base64_encode(nego->output_token, nego->output_token_length, outptr, outlen); if(!result && (!*outptr || !*outlen)) { - free(*outptr); + curlx_free(*outptr); result = CURLE_REMOTE_ACCESS_DENIED; } @@ -328,14 +318,14 @@ void Curl_auth_cleanup_spnego(struct negotiatedata *nego) /* Free our security context */ if(nego->context) { Curl_pSecFn->DeleteSecurityContext(nego->context); - free(nego->context); + curlx_free(nego->context); nego->context = NULL; } /* Free our credentials handle */ if(nego->credentials) { Curl_pSecFn->FreeCredentialsHandle(nego->credentials); - free(nego->credentials); + curlx_free(nego->credentials); nego->credentials = NULL; } diff --git a/lib/vauth/vauth.c b/lib/vauth/vauth.c index 6ee687dcab22..61f79037a3bb 100644 --- a/lib/vauth/vauth.c +++ b/lib/vauth/vauth.c @@ -24,18 +24,10 @@ #include "../curl_setup.h" -#include - #include "vauth.h" -#include "../strdup.h" -#include "../urldata.h" #include "../curlx/multibyte.h" #include "../url.h" -/* The last #include files should be: */ -#include "../curl_memory.h" -#include "../memdebug.h" - /* * Curl_auth_build_spn() * @@ -76,7 +68,6 @@ TCHAR *Curl_auth_build_spn(const char *service, const char *host, { char *utf8_spn = NULL; TCHAR *tchar_spn = NULL; - TCHAR *dupe_tchar_spn = NULL; (void)realm; @@ -92,16 +83,11 @@ TCHAR *Curl_auth_build_spn(const char *service, const char *host, if(!utf8_spn) return NULL; - /* Allocate and return a TCHAR based SPN. Since curlx_convert_UTF8_to_tchar - must be freed by curlx_unicodefree we will dupe the result so that the - pointer this function returns can be normally free'd. */ + /* Allocate and return a TCHAR based SPN. */ tchar_spn = curlx_convert_UTF8_to_tchar(utf8_spn); - free(utf8_spn); - if(!tchar_spn) - return NULL; - dupe_tchar_spn = Curl_tcsdup(tchar_spn); - curlx_unicodefree(tchar_spn); - return dupe_tchar_spn; + curlx_free(utf8_spn); + + return tchar_spn; } #endif /* USE_WINDOWS_SSPI */ @@ -170,18 +156,16 @@ static void ntlm_conn_dtor(void *key, size_t klen, void *entry) (void)klen; DEBUGASSERT(ntlm); Curl_auth_cleanup_ntlm(ntlm); - free(ntlm); + curlx_free(ntlm); } struct ntlmdata *Curl_auth_ntlm_get(struct connectdata *conn, bool proxy) { - const char *key = proxy ? CURL_META_NTLM_PROXY_CONN : - CURL_META_NTLM_CONN; + const char *key = proxy ? CURL_META_NTLM_PROXY_CONN : CURL_META_NTLM_CONN; struct ntlmdata *ntlm = Curl_conn_meta_get(conn, key); if(!ntlm) { - ntlm = calloc(1, sizeof(*ntlm)); - if(!ntlm || - Curl_conn_meta_set(conn, key, ntlm, ntlm_conn_dtor)) + ntlm = curlx_calloc(1, sizeof(*ntlm)); + if(!ntlm || Curl_conn_meta_set(conn, key, ntlm, ntlm_conn_dtor)) return NULL; } return ntlm; @@ -189,8 +173,8 @@ struct ntlmdata *Curl_auth_ntlm_get(struct connectdata *conn, bool proxy) void Curl_auth_ntlm_remove(struct connectdata *conn, bool proxy) { - Curl_conn_meta_remove(conn, proxy ? - CURL_META_NTLM_PROXY_CONN : CURL_META_NTLM_CONN); + Curl_conn_meta_remove(conn, proxy ? CURL_META_NTLM_PROXY_CONN + : CURL_META_NTLM_CONN); } #endif /* USE_NTLM */ @@ -204,14 +188,14 @@ static void krb5_conn_dtor(void *key, size_t klen, void *entry) (void)klen; DEBUGASSERT(krb5); Curl_auth_cleanup_gssapi(krb5); - free(krb5); + curlx_free(krb5); } struct kerberos5data *Curl_auth_krb5_get(struct connectdata *conn) { struct kerberos5data *krb5 = Curl_conn_meta_get(conn, CURL_META_KRB5_CONN); if(!krb5) { - krb5 = calloc(1, sizeof(*krb5)); + krb5 = curlx_calloc(1, sizeof(*krb5)); if(!krb5 || Curl_conn_meta_set(conn, CURL_META_KRB5_CONN, krb5, krb5_conn_dtor)) return NULL; @@ -230,14 +214,14 @@ static void gsasl_conn_dtor(void *key, size_t klen, void *entry) (void)klen; DEBUGASSERT(gsasl); Curl_auth_gsasl_cleanup(gsasl); - free(gsasl); + curlx_free(gsasl); } struct gsasldata *Curl_auth_gsasl_get(struct connectdata *conn) { struct gsasldata *gsasl = Curl_conn_meta_get(conn, CURL_META_GSASL_CONN); if(!gsasl) { - gsasl = calloc(1, sizeof(*gsasl)); + gsasl = curlx_calloc(1, sizeof(*gsasl)); if(!gsasl || Curl_conn_meta_set(conn, CURL_META_GSASL_CONN, gsasl, gsasl_conn_dtor)) return NULL; @@ -256,18 +240,16 @@ static void nego_conn_dtor(void *key, size_t klen, void *entry) (void)klen; DEBUGASSERT(nego); Curl_auth_cleanup_spnego(nego); - free(nego); + curlx_free(nego); } struct negotiatedata *Curl_auth_nego_get(struct connectdata *conn, bool proxy) { - const char *key = proxy ? CURL_META_NEGO_PROXY_CONN : - CURL_META_NEGO_CONN; + const char *key = proxy ? CURL_META_NEGO_PROXY_CONN : CURL_META_NEGO_CONN; struct negotiatedata *nego = Curl_conn_meta_get(conn, key); if(!nego) { - nego = calloc(1, sizeof(*nego)); - if(!nego || - Curl_conn_meta_set(conn, key, nego, nego_conn_dtor)) + nego = curlx_calloc(1, sizeof(*nego)); + if(!nego || Curl_conn_meta_set(conn, key, nego, nego_conn_dtor)) return NULL; } return nego; diff --git a/lib/vauth/vauth.h b/lib/vauth/vauth.h index 9a33ca0c2317..39dc0d3995fb 100644 --- a/lib/vauth/vauth.h +++ b/lib/vauth/vauth.h @@ -24,10 +24,11 @@ * ***************************************************************************/ -#include +#include "../curl_setup.h" #include "../bufref.h" #include "../curlx/dynbuf.h" +#include "../urldata.h" struct Curl_easy; struct connectdata; @@ -233,14 +234,6 @@ CURLcode Curl_auth_create_xoauth_bearer_message(const char *user, #ifdef USE_KERBEROS5 -#ifdef HAVE_GSSAPI -# ifdef HAVE_GSSGNU -# include -# else -# include -# endif -#endif - /* meta key for storing KRB5 meta at connection */ #define CURL_META_KRB5_CONN "meta:auth:krb5:conn" @@ -306,7 +299,9 @@ struct negotiatedata { gss_ctx_id_t context; gss_name_t spn; gss_buffer_desc output_token; +#ifdef GSS_C_CHANNEL_BOUND_FLAG struct dynbuf channel_binding_data; +#endif #else #ifdef USE_WINDOWS_SSPI #ifdef SECPKG_ATTR_ENDPOINT_BINDINGS diff --git a/lib/version.c b/lib/version.c index 4c7e5712f0f9..a5be6c69cf73 100644 --- a/lib/version.c +++ b/lib/version.c @@ -28,7 +28,6 @@ #include #endif -#include #include "urldata.h" #include "vtls/vtls.h" #include "http2.h" @@ -77,16 +76,8 @@ #include #endif -#ifdef HAVE_GSSAPI -# ifdef HAVE_GSSGNU -# include -# else -# include -# endif -#endif - -#ifdef USE_OPENLDAP -#include +#ifndef CURL_DISABLE_LDAP +#include "curl_ldap.h" #endif #ifdef HAVE_BROTLI @@ -111,28 +102,6 @@ static void zstd_version(char *buf, size_t bufsz) } #endif -#ifdef USE_OPENLDAP -static void oldap_version(char *buf, size_t bufsz) -{ - LDAPAPIInfo api; - api.ldapai_info_version = LDAP_API_INFO_VERSION; - - if(ldap_get_option(NULL, LDAP_OPT_API_INFO, &api) == LDAP_OPT_SUCCESS) { - unsigned int patch = (unsigned int)(api.ldapai_vendor_version % 100); - unsigned int major = (unsigned int)(api.ldapai_vendor_version / 10000); - unsigned int minor = - (((unsigned int)api.ldapai_vendor_version - major * 10000) - - patch) / 100; - curl_msnprintf(buf, bufsz, "%s/%u.%u.%u", - api.ldapai_vendor_name, major, minor, patch); - ldap_memfree(api.ldapai_vendor_name); - ber_memvfree((void **)api.ldapai_extensions); - } - else - curl_msnprintf(buf, bufsz, "OpenLDAP"); -} -#endif - #ifdef USE_LIBPSL static void psl_version(char *buf, size_t bufsz) { @@ -219,7 +188,7 @@ char *curl_version(void) #ifdef HAVE_GSSAPI char gss_buf[40]; #endif -#ifdef USE_OPENLDAP +#ifndef CURL_DISABLE_LDAP char ldap_buf[30]; #endif int i = 0; @@ -297,8 +266,8 @@ char *curl_version(void) #endif src[i++] = gss_buf; #endif /* HAVE_GSSAPI */ -#ifdef USE_OPENLDAP - oldap_version(ldap_buf, sizeof(ldap_buf)); +#ifndef CURL_DISABLE_LDAP + Curl_ldap_version(ldap_buf, sizeof(ldap_buf)); src[i++] = ldap_buf; #endif @@ -365,8 +334,8 @@ static const char * const supported_protocols[] = { #ifndef CURL_DISABLE_LDAP "ldap", #if !defined(CURL_DISABLE_LDAPS) && \ - ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ - (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) + ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \ + (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))) "ldaps", #endif #endif @@ -468,7 +437,7 @@ static int ech_present(curl_version_info_data *info) * Use FEATURE() macro to define an entry: this allows documentation check. */ -#define FEATURE(name, present, bitmask) {(name), (present), (bitmask)} +#define FEATURE(name, present, bitmask) { (name), (present), (bitmask) } struct feat { const char *name; @@ -530,8 +499,7 @@ static const struct feat features_table[] = { #ifdef USE_KERBEROS5 FEATURE("Kerberos", NULL, CURL_VERSION_KERBEROS5), #endif -#if (SIZEOF_CURL_OFF_T > 4) && \ - ( (SIZEOF_OFF_T > 4) || defined(USE_WIN32_LARGE_FILES) ) +#if (SIZEOF_CURL_OFF_T > 4) && ((SIZEOF_OFF_T > 4) || defined(_WIN32)) FEATURE("Largefile", NULL, CURL_VERSION_LARGEFILE), #endif #ifdef HAVE_LIBZ @@ -582,9 +550,7 @@ static const struct feat features_table[] = { {NULL, NULL, 0} }; -static const char *feature_names[sizeof(features_table) / - sizeof(features_table[0])] = {NULL}; - +static const char *feature_names[CURL_ARRAYSIZE(features_table)] = { NULL }; static curl_version_info_data version_info = { CURLVERSION_NOW, diff --git a/lib/vquic/curl_ngtcp2.c b/lib/vquic/curl_ngtcp2.c index 53665b1a3d1d..20b9240f09ed 100644 --- a/lib/vquic/curl_ngtcp2.c +++ b/lib/vquic/curl_ngtcp2.c @@ -49,8 +49,7 @@ #include "../urldata.h" #include "../url.h" #include "../uint-hash.h" -#include "../sendf.h" -#include "../strdup.h" +#include "../curl_trc.h" #include "../rand.h" #include "../multiif.h" #include "../cfilters.h" @@ -60,8 +59,8 @@ #include "../curlx/dynbuf.h" #include "../http1.h" #include "../select.h" -#include "../curlx/inet_pton.h" #include "../transfer.h" +#include "../bufref.h" #include "vquic.h" #include "vquic_int.h" #include "vquic-tls.h" @@ -70,22 +69,18 @@ #include "../vtls/vtls_scache.h" #include "curl_ngtcp2.h" -#include "../curlx/warnless.h" -/* The last 2 #include files should be in this order */ -#include "../curl_memory.h" -#include "../memdebug.h" - - -#define QUIC_MAX_STREAMS (256*1024) -#define QUIC_HANDSHAKE_TIMEOUT (10*NGTCP2_SECONDS) +#define QUIC_MAX_STREAMS (256 * 1024) +#define QUIC_HANDSHAKE_TIMEOUT (10 * NGTCP2_SECONDS) /* 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. + * each active transfer. * 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) +#define H3_STREAM_WINDOW_SIZE_INITIAL (32 * 1024) +#define H3_STREAM_WINDOW_SIZE_MAX (10 * 1024 * 1024) +#define H3_CONN_WINDOW_SIZE_MAX (100 * H3_STREAM_WINDOW_SIZE_MAX) + +#define H3_STREAM_CHUNK_SIZE (64 * 1024) #if H3_STREAM_CHUNK_SIZE < NGTCP2_MAX_UDP_PAYLOAD_SIZE #error H3_STREAM_CHUNK_SIZE smaller than NGTCP2_MAX_UDP_PAYLOAD_SIZE #endif @@ -95,13 +90,11 @@ * The benefit of the pool is that stream buffer to not keep * spares. 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 +#define H3_STREAM_POOL_SPARES 2 /* Receive and Send max number of chunks just follows from the * chunk size and window size */ #define H3_STREAM_SEND_CHUNKS \ - (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE) - + (H3_STREAM_WINDOW_SIZE_MAX / H3_STREAM_CHUNK_SIZE) /* * Store ngtcp2 version info in this buffer. @@ -138,7 +131,6 @@ struct cf_ngtcp2_ctx { struct bufc_pool stream_bufcp; /* chunk pool for streams */ struct dynbuf scratch; /* temp buffer for header construction */ struct uint_hash streams; /* hash `data->mid` to `h3_stream_ctx` */ - size_t max_stream_window; /* max flow window for one stream */ uint64_t used_bidi_streams; /* bidi streams we have opened */ uint64_t max_bidi_streams; /* max bidi streams we can open */ size_t earlydata_max; /* max amount of early data supported by @@ -156,8 +148,7 @@ struct cf_ngtcp2_ctx { /* How to access `call_data` from a cf_ngtcp2 filter */ #undef CF_CTX_CALL_DATA -#define CF_CTX_CALL_DATA(cf) \ - ((struct cf_ngtcp2_ctx *)(cf)->ctx)->call_data +#define CF_CTX_CALL_DATA(cf) ((struct cf_ngtcp2_ctx *)(cf)->ctx)->call_data static void h3_stream_hash_free(unsigned int id, void *stream); @@ -166,11 +157,10 @@ static void cf_ngtcp2_ctx_init(struct cf_ngtcp2_ctx *ctx) DEBUGASSERT(!ctx->initialized); ctx->qlogfd = -1; ctx->version = NGTCP2_PROTO_VER_MAX; - ctx->max_stream_window = H3_STREAM_WINDOW_SIZE; Curl_bufcp_init(&ctx->stream_bufcp, H3_STREAM_CHUNK_SIZE, H3_STREAM_POOL_SPARES); curlx_dyn_init(&ctx->scratch, CURL_MAX_HTTP_HEADER); - Curl_uint_hash_init(&ctx->streams, 63, h3_stream_hash_free); + Curl_uint32_hash_init(&ctx->streams, 63, h3_stream_hash_free); ctx->initialized = TRUE; } @@ -181,10 +171,10 @@ static void cf_ngtcp2_ctx_free(struct cf_ngtcp2_ctx *ctx) vquic_ctx_free(&ctx->q); Curl_bufcp_free(&ctx->stream_bufcp); curlx_dyn_free(&ctx->scratch); - Curl_uint_hash_destroy(&ctx->streams); + Curl_uint32_hash_destroy(&ctx->streams); Curl_ssl_peer_cleanup(&ctx->peer); } - free(ctx); + curlx_free(ctx); } static void cf_ngtcp2_setup_keep_alive(struct Curl_cfilter *cf, @@ -193,14 +183,14 @@ static void cf_ngtcp2_setup_keep_alive(struct Curl_cfilter *cf, struct cf_ngtcp2_ctx *ctx = cf->ctx; const ngtcp2_transport_params *rp; /* Peer should have sent us its transport parameters. If it - * announces a positive `max_idle_timeout` it will close the - * connection when it does not hear from us for that time. - * - * Some servers use this as a keep-alive timer at a rather low - * value. We are doing HTTP/3 here and waiting for the response - * to a request may take a considerable amount of time. We need - * to prevent the peer's QUIC stack from closing in this case. - */ + * announces a positive `max_idle_timeout` it will close the + * connection when it does not hear from us for that time. + * + * Some servers use this as a keep-alive timer at a rather low + * value. We are doing HTTP/3 here and waiting for the response + * to a request may take a considerable amount of time. We need + * to prevent the peer's QUIC stack from closing in this case. + */ if(!ctx->qconn) return; @@ -209,7 +199,7 @@ static void cf_ngtcp2_setup_keep_alive(struct Curl_cfilter *cf, ngtcp2_conn_set_keep_alive_timeout(ctx->qconn, UINT64_MAX); CURL_TRC_CF(data, cf, "no peer idle timeout, unset keep-alive"); } - else if(!Curl_uint_hash_count(&ctx->streams)) { + else if(!Curl_uint32_hash_count(&ctx->streams)) { ngtcp2_conn_set_keep_alive_timeout(ctx->qconn, UINT64_MAX); CURL_TRC_CF(data, cf, "no active streams, unset keep-alive"); } @@ -217,14 +207,13 @@ static void cf_ngtcp2_setup_keep_alive(struct Curl_cfilter *cf, ngtcp2_duration keep_ns; keep_ns = (rp->max_idle_timeout > 1) ? (rp->max_idle_timeout / 2) : 1; ngtcp2_conn_set_keep_alive_timeout(ctx->qconn, keep_ns); - CURL_TRC_CF(data, cf, "peer idle timeout is %" FMT_PRIu64 "ms, " - "set keep-alive to %" FMT_PRIu64 " ms.", - (curl_uint64_t)(rp->max_idle_timeout / NGTCP2_MILLISECONDS), - (curl_uint64_t)(keep_ns / NGTCP2_MILLISECONDS)); + CURL_TRC_CF(data, cf, "peer idle timeout is %" PRIu64 "ms, " + "set keep-alive to %" PRIu64 " ms.", + (rp->max_idle_timeout / NGTCP2_MILLISECONDS), + (keep_ns / NGTCP2_MILLISECONDS)); } } - struct pkt_io_ctx; static CURLcode cf_progress_ingress(struct Curl_cfilter *cf, struct Curl_easy *data, @@ -237,26 +226,28 @@ static CURLcode cf_progress_egress(struct Curl_cfilter *cf, * All about the H3 internals of a stream */ struct h3_stream_ctx { - curl_int64_t id; /* HTTP/3 protocol identifier */ - struct bufq sendbuf; /* h3 request body */ - struct h1_req_parser h1; /* h1 request parsing */ + int64_t id; /* HTTP/3 protocol identifier */ + struct bufq sendbuf; /* h3 request body */ + struct h1_req_parser h1; /* h1 request parsing */ size_t sendbuf_len_in_flight; /* sendbuf amount "in flight" */ - curl_uint64_t error3; /* HTTP/3 stream error code */ - curl_off_t upload_left; /* number of request bytes left to upload */ - int status_code; /* HTTP status code */ - CURLcode xfer_result; /* result from xfer_resp_write(_hd) */ - BIT(resp_hds_complete); /* we have a complete, final response */ - BIT(closed); /* TRUE on stream close */ - BIT(reset); /* TRUE on stream reset */ - BIT(send_closed); /* stream is local closed */ - BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */ + uint64_t error3; /* HTTP/3 stream error code */ + curl_off_t upload_left; /* number of request bytes left to upload */ + uint64_t download_unacked; /* bytes not acknowledged yet */ + uint64_t window_size_max; /* max flow control window set for stream */ + int status_code; /* HTTP status code */ + CURLcode xfer_result; /* result from xfer_resp_write(_hd) */ + BIT(resp_hds_complete); /* we have a complete, final response */ + BIT(closed); /* TRUE on stream close */ + BIT(reset); /* TRUE on stream reset */ + BIT(send_closed); /* stream is local closed */ + BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */ }; static void h3_stream_ctx_free(struct h3_stream_ctx *stream) { Curl_bufq_free(&stream->sendbuf); Curl_h1_req_parse_free(&stream->h1); - free(stream); + curlx_free(stream); } static void h3_stream_hash_free(unsigned int id, void *stream) @@ -278,7 +269,7 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf, if(stream) return CURLE_OK; - stream = calloc(1, sizeof(*stream)); + stream = curlx_calloc(1, sizeof(*stream)); if(!stream) return CURLE_OUT_OF_MEMORY; @@ -287,26 +278,28 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf, Curl_bufq_initp(&stream->sendbuf, &ctx->stream_bufcp, H3_STREAM_SEND_CHUNKS, BUFQ_OPT_NONE); stream->sendbuf_len_in_flight = 0; + stream->window_size_max = H3_STREAM_WINDOW_SIZE_INITIAL; Curl_h1_req_parse_init(&stream->h1, H1_PARSE_DEFAULT_MAX_LINE_LEN); - if(!Curl_uint_hash_set(&ctx->streams, data->mid, stream)) { + if(!Curl_uint32_hash_set(&ctx->streams, data->mid, stream)) { h3_stream_ctx_free(stream); return CURLE_OUT_OF_MEMORY; } - if(Curl_uint_hash_count(&ctx->streams) == 1) + if(Curl_uint32_hash_count(&ctx->streams) == 1) cf_ngtcp2_setup_keep_alive(cf, data); return CURLE_OK; } +#if NGTCP2_VERSION_NUM < 0x011100 struct cf_ngtcp2_sfind_ctx { - curl_int64_t stream_id; + int64_t stream_id; struct h3_stream_ctx *stream; - unsigned int mid; + uint32_t mid; }; -static bool cf_ngtcp2_sfind(unsigned int mid, void *value, void *user_data) +static bool cf_ngtcp2_sfind(uint32_t mid, void *value, void *user_data) { struct cf_ngtcp2_sfind_ctx *fctx = user_data; struct h3_stream_ctx *stream = value; @@ -319,15 +312,29 @@ static bool cf_ngtcp2_sfind(unsigned int mid, void *value, void *user_data) return TRUE; /* continue */ } -static struct h3_stream_ctx * -cf_ngtcp2_get_stream(struct cf_ngtcp2_ctx *ctx, curl_int64_t stream_id) +static struct h3_stream_ctx *cf_ngtcp2_get_stream(struct cf_ngtcp2_ctx *ctx, + int64_t stream_id) { struct cf_ngtcp2_sfind_ctx fctx; fctx.stream_id = stream_id; fctx.stream = NULL; - Curl_uint_hash_visit(&ctx->streams, cf_ngtcp2_sfind, &fctx); + Curl_uint32_hash_visit(&ctx->streams, cf_ngtcp2_sfind, &fctx); return fctx.stream; } +#else +static struct h3_stream_ctx *cf_ngtcp2_get_stream(struct cf_ngtcp2_ctx *ctx, + int64_t stream_id) +{ + struct Curl_easy *data = + ngtcp2_conn_get_stream_user_data(ctx->qconn, stream_id); + + if(!data) { + return NULL; + } + + return H3_STREAM_CTX(ctx, data); +} +#endif static void cf_ngtcp2_stream_close(struct Curl_cfilter *cf, struct Curl_easy *data, @@ -346,7 +353,7 @@ static void cf_ngtcp2_stream_close(struct Curl_cfilter *cf, NGHTTP3_H3_REQUEST_CANCELLED); result = cf_progress_egress(cf, data, NULL); if(result) - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] cancel stream -> %d", + CURL_TRC_CF(data, cf, "[%" PRId64 "] cancel stream -> %d", stream->id, result); } } @@ -357,11 +364,10 @@ static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data) struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); (void)cf; if(stream) { - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] easy handle is done", - stream->id); + CURL_TRC_CF(data, cf, "[%" PRId64 "] easy handle is done", stream->id); cf_ngtcp2_stream_close(cf, data, stream); - Curl_uint_hash_remove(&ctx->streams, data->mid); - if(!Curl_uint_hash_count(&ctx->streams)) + Curl_uint32_hash_remove(&ctx->streams, data->mid); + if(!Curl_uint32_hash_count(&ctx->streams)) cf_ngtcp2_setup_keep_alive(cf, data); } } @@ -377,24 +383,31 @@ struct pkt_io_ctx { ngtcp2_path_storage ps; }; -static void pktx_update_time(struct pkt_io_ctx *pktx, +static void pktx_update_time(struct Curl_easy *data, + struct pkt_io_ctx *pktx, struct Curl_cfilter *cf) { struct cf_ngtcp2_ctx *ctx = cf->ctx; + const struct curltime *pnow = Curl_pgrs_now(data); - vquic_ctx_update_time(&ctx->q); - pktx->ts = (ngtcp2_tstamp)ctx->q.last_op.tv_sec * NGTCP2_SECONDS + - (ngtcp2_tstamp)ctx->q.last_op.tv_usec * NGTCP2_MICROSECONDS; + vquic_ctx_update_time(&ctx->q, pnow); + pktx->ts = (ngtcp2_tstamp)pnow->tv_sec * NGTCP2_SECONDS + + (ngtcp2_tstamp)pnow->tv_usec * NGTCP2_MICROSECONDS; } static void pktx_init(struct pkt_io_ctx *pktx, struct Curl_cfilter *cf, struct Curl_easy *data) { + struct cf_ngtcp2_ctx *ctx = cf->ctx; + const struct curltime *pnow = Curl_pgrs_now(data); + pktx->cf = cf; pktx->data = data; ngtcp2_path_storage_zero(&pktx->ps); - pktx_update_time(pktx, cf); + vquic_ctx_set_time(&ctx->q, pnow); + pktx->ts = (ngtcp2_tstamp)pnow->tv_sec * NGTCP2_SECONDS + + (ngtcp2_tstamp)pnow->tv_usec * NGTCP2_MICROSECONDS; } static int cb_h3_acked_req_body(nghttp3_conn *conn, int64_t stream_id, @@ -443,17 +456,6 @@ static void quic_settings(struct cf_ngtcp2_ctx *ctx, struct Curl_easy *data, struct pkt_io_ctx *pktx) { -#ifdef NGTCP2_SETTINGS_V2x -static uint16_t mtu_probes[] = { - 1472, /* what h2o offers */ - 1452, /* what Caddy offers */ - 1454 - 48, /* The well known MTU used by a domestic optic fiber - service in Japan. */ - 1390 - 48, /* Typical Tunneled MTU */ - 1280 - 48, /* IPv6 minimum MTU */ - 1492 - 48, /* PPPoE */ -}; -#endif ngtcp2_settings *s = &ctx->settings; ngtcp2_transport_params *t = &ctx->transport_params; @@ -468,19 +470,18 @@ static uint16_t mtu_probes[] = { s->initial_ts = pktx->ts; s->handshake_timeout = (data->set.connecttimeout > 0) ? data->set.connecttimeout * NGTCP2_MILLISECONDS : QUIC_HANDSHAKE_TIMEOUT; - s->max_window = 100 * ctx->max_stream_window; - s->max_stream_window = 10 * ctx->max_stream_window; + s->max_window = H3_CONN_WINDOW_SIZE_MAX; + s->max_stream_window = 0; /* disable ngtcp2 auto-tuning of window */ s->no_pmtud = FALSE; -#ifdef NGTCP2_SETTINGS_V2x - s->pmtud_probes = mtu_probes; - s->pmtud_probeslen = CURL_ARRAYSIZE(mtu_probes); - s->max_tx_udp_payload_size = 64 * 1024; /* mtu_probes[0]; */ +#ifdef NGTCP2_SETTINGS_V3 + /* try ten times the ngtcp2 defaults here for problems with Caddy */ + s->glitch_ratelim_burst = 1000 * 10; + s->glitch_ratelim_rate = 33 * 10; #endif - - t->initial_max_data = 10 * ctx->max_stream_window; - t->initial_max_stream_data_bidi_local = ctx->max_stream_window; - t->initial_max_stream_data_bidi_remote = ctx->max_stream_window; - t->initial_max_stream_data_uni = ctx->max_stream_window; + t->initial_max_data = s->max_window; + t->initial_max_stream_data_bidi_local = H3_STREAM_WINDOW_SIZE_INITIAL; + t->initial_max_stream_data_bidi_remote = H3_STREAM_WINDOW_SIZE_INITIAL; + t->initial_max_stream_data_uni = t->initial_max_data; t->initial_max_streams_bidi = QUIC_MAX_STREAMS; t->initial_max_streams_uni = QUIC_MAX_STREAMS; t->max_idle_timeout = 0; /* no idle timeout from our side */ @@ -505,23 +506,24 @@ static int cf_ngtcp2_handshake_completed(ngtcp2_conn *tconn, void *user_data) if(!ctx || !data) return NGHTTP3_ERR_CALLBACK_FAILURE; - ctx->handshake_at = curlx_now(); + ctx->handshake_at = *Curl_pgrs_now(data); ctx->tls_handshake_complete = TRUE; Curl_vquic_report_handshake(&ctx->tls, cf, data); ctx->tls_vrfy_result = Curl_vquic_tls_verify_peer(&ctx->tls, cf, data, &ctx->peer); +#ifndef CURL_DISABLE_VERBOSE_STRINGS if(Curl_trc_is_verbose(data)) { const ngtcp2_transport_params *rp; rp = ngtcp2_conn_get_remote_transport_params(ctx->qconn); - CURL_TRC_CF(data, cf, "handshake complete after %dms, remote transport[" - "max_udp_payload=%" FMT_PRIu64 - ", initial_max_data=%" FMT_PRIu64 + CURL_TRC_CF(data, cf, "handshake complete after %" FMT_TIMEDIFF_T + "ms, remote transport[max_udp_payload=%" PRIu64 + ", initial_max_data=%" PRIu64 "]", - (int)curlx_timediff(ctx->handshake_at, ctx->started_at), - (curl_uint64_t)rp->max_udp_payload_size, - (curl_uint64_t)rp->initial_max_data); + curlx_ptimediff_ms(&ctx->handshake_at, &ctx->started_at), + rp->max_udp_payload_size, rp->initial_max_data); } +#endif /* In case of earlydata, where we simulate being connected, update * the handshake time when we really did connect */ @@ -603,13 +605,12 @@ static void cf_ngtcp2_h3_err_set(struct Curl_cfilter *cf, } static int cb_recv_stream_data(ngtcp2_conn *tconn, uint32_t flags, - int64_t sid, uint64_t offset, + int64_t stream_id, uint64_t offset, const uint8_t *buf, size_t buflen, void *user_data, void *stream_user_data) { struct Curl_cfilter *cf = user_data; struct cf_ngtcp2_ctx *ctx = cf->ctx; - curl_int64_t stream_id = (curl_int64_t)sid; nghttp3_ssize nconsumed; int fin = (flags & NGTCP2_STREAM_DATA_FLAG_FIN) ? 1 : 0; struct Curl_easy *data = stream_user_data; @@ -621,12 +622,12 @@ static int cb_recv_stream_data(ngtcp2_conn *tconn, uint32_t flags, if(!data) data = CF_DATA_CURRENT(cf); if(data) - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] read_stream(len=%zu) -> %zd", + CURL_TRC_CF(data, cf, "[%" PRId64 "] read_stream(len=%zu) -> %zd", stream_id, buflen, nconsumed); if(nconsumed < 0) { struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); if(data && stream) { - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] error on known stream, " + CURL_TRC_CF(data, cf, "[%" PRId64 "] error on known stream, " "reset=%d, closed=%d", stream_id, stream->reset, stream->closed); } @@ -642,10 +643,9 @@ static int cb_recv_stream_data(ngtcp2_conn *tconn, uint32_t flags, return 0; } -static int -cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id, - uint64_t offset, uint64_t datalen, void *user_data, - void *stream_user_data) +static int cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id, + uint64_t offset, uint64_t datalen, + void *user_data, void *stream_user_data) { struct Curl_cfilter *cf = user_data; struct cf_ngtcp2_ctx *ctx = cf->ctx; @@ -665,13 +665,12 @@ cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id, } static int cb_stream_close(ngtcp2_conn *tconn, uint32_t flags, - int64_t sid, uint64_t app_error_code, + int64_t stream_id, uint64_t app_error_code, void *user_data, void *stream_user_data) { struct Curl_cfilter *cf = user_data; struct cf_ngtcp2_ctx *ctx = cf->ctx; struct Curl_easy *data = stream_user_data; - curl_int64_t stream_id = (curl_int64_t)sid; int rv; (void)tconn; @@ -686,9 +685,8 @@ static int cb_stream_close(ngtcp2_conn *tconn, uint32_t flags, } rv = nghttp3_conn_close_stream(ctx->h3conn, stream_id, app_error_code); - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] quic close(app_error=%" - FMT_PRIu64 ") -> %d", stream_id, (curl_uint64_t)app_error_code, - rv); + CURL_TRC_CF(data, cf, "[%" PRId64 "] quic close(app_error=%" + PRIu64 ") -> %d", stream_id, app_error_code, rv); if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) { cf_ngtcp2_h3_err_set(cf, data, rv); return NGTCP2_ERR_CALLBACK_FAILURE; @@ -697,13 +695,12 @@ static int cb_stream_close(ngtcp2_conn *tconn, uint32_t flags, return 0; } -static int cb_stream_reset(ngtcp2_conn *tconn, int64_t sid, +static int cb_stream_reset(ngtcp2_conn *tconn, int64_t stream_id, uint64_t final_size, uint64_t app_error_code, void *user_data, void *stream_user_data) { struct Curl_cfilter *cf = user_data; struct cf_ngtcp2_ctx *ctx = cf->ctx; - curl_int64_t stream_id = (curl_int64_t)sid; struct Curl_easy *data = stream_user_data; int rv; (void)tconn; @@ -712,7 +709,7 @@ static int cb_stream_reset(ngtcp2_conn *tconn, int64_t sid, (void)data; rv = nghttp3_conn_shutdown_stream_read(ctx->h3conn, stream_id); - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] reset -> %d", stream_id, rv); + CURL_TRC_CF(data, cf, "[%" PRId64 "] reset -> %d", stream_id, rv); if(rv && rv != NGHTTP3_ERR_STREAM_NOT_FOUND) { return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -750,9 +747,8 @@ static int cb_extend_max_local_streams_bidi(ngtcp2_conn *tconn, (void)tconn; ctx->max_bidi_streams = max_streams; if(data) - CURL_TRC_CF(data, cf, "max bidi streams now %" FMT_PRIu64 - ", used %" FMT_PRIu64, (curl_uint64_t)ctx->max_bidi_streams, - (curl_uint64_t)ctx->used_bidi_streams); + CURL_TRC_CF(data, cf, "max bidi streams now %" PRIu64 ", used %" PRIu64, + ctx->max_bidi_streams, ctx->used_bidi_streams); return 0; } @@ -774,8 +770,7 @@ static int cb_extend_max_stream_data(ngtcp2_conn *tconn, int64_t stream_id, } stream = H3_STREAM_CTX(ctx, s_data); if(stream && stream->quic_flow_blocked) { - CURL_TRC_CF(s_data, cf, "[%" FMT_PRId64 "] unblock quic flow", - (curl_int64_t)stream_id); + CURL_TRC_CF(s_data, cf, "[%" PRId64 "] unblock quic flow", stream_id); stream->quic_flow_blocked = FALSE; Curl_multi_mark_dirty(s_data); } @@ -837,8 +832,8 @@ static int cb_recv_rx_key(ngtcp2_conn *tconn, ngtcp2_encryption_level level, } #if defined(_MSC_VER) && defined(_DLL) -# pragma warning(push) -# pragma warning(disable:4232) /* MSVC extension, dllimport identity */ +#pragma warning(push) +#pragma warning(disable:4232) /* MSVC extension, dllimport identity */ #endif static ngtcp2_callbacks ng_callbacks = { @@ -888,7 +883,7 @@ static ngtcp2_callbacks ng_callbacks = { }; #if defined(_MSC_VER) && defined(_DLL) -# pragma warning(pop) +#pragma warning(pop) #endif /** @@ -911,7 +906,7 @@ static CURLcode check_and_set_expiry(struct Curl_cfilter *cf, pktx = &local_pktx; } else { - pktx_update_time(pktx, cf); + pktx_update_time(data, pktx, cf); } expiry = ngtcp2_conn_get_expiry(ctx->qconn); @@ -969,7 +964,7 @@ static CURLcode cf_ngtcp2_adjust_pollset(struct Curl_cfilter *cf, 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)); + !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); @@ -982,14 +977,13 @@ static CURLcode cf_ngtcp2_adjust_pollset(struct Curl_cfilter *cf, return result; } -static int cb_h3_stream_close(nghttp3_conn *conn, int64_t sid, +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 cf_ngtcp2_ctx *ctx = cf->ctx; struct Curl_easy *data = stream_user_data; - curl_int64_t stream_id = (curl_int64_t)sid; struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); (void)conn; (void)stream_id; @@ -999,15 +993,15 @@ static int cb_h3_stream_close(nghttp3_conn *conn, int64_t sid, return 0; stream->closed = TRUE; - stream->error3 = (curl_uint64_t)app_error_code; + stream->error3 = app_error_code; if(stream->error3 != NGHTTP3_H3_NO_ERROR) { stream->reset = TRUE; stream->send_closed = TRUE; - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] RESET: error %" FMT_PRIu64, + CURL_TRC_CF(data, cf, "[%" PRId64 "] RESET: error %" PRIu64, stream->id, stream->error3); } else { - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] CLOSED", stream->id); + CURL_TRC_CF(data, cf, "[%" PRId64 "] CLOSED", stream->id); } Curl_multi_mark_dirty(data); return 0; @@ -1018,12 +1012,16 @@ static void h3_xfer_write_resp_hd(struct Curl_cfilter *cf, struct h3_stream_ctx *stream, const char *buf, size_t blen, bool eos) { - - /* If we already encountered an error, skip further writes */ + /* This function returns no error intentionally, but records + * the result at the stream, skipping further writes once the + * `result` of the transfer is known. + * The stream is subsequently cancelled "higher up" in the filter's + * send/recv callbacks. Closing the stream here leads to SEND/RECV + * errors in other places that then overwrite the transfer's result. */ if(!stream->xfer_result) { stream->xfer_result = Curl_xfer_write_resp_hd(data, buf, blen, eos); if(stream->xfer_result) - CURL_TRC_CF(data, cf, "[%"FMT_PRId64"] error %d writing %zu " + CURL_TRC_CF(data, cf, "[%" PRId64 "] error %d writing %zu " "bytes of headers", stream->id, stream->xfer_result, blen); } } @@ -1033,16 +1031,73 @@ static void h3_xfer_write_resp(struct Curl_cfilter *cf, struct h3_stream_ctx *stream, const char *buf, size_t blen, bool eos) { - - /* If we already encountered an error, skip further writes */ + /* This function returns no error intentionally, but records + * the result at the stream, skipping further writes once the + * `result` of the transfer is known. + * The stream is subsequently cancelled "higher up" in the filter's + * send/recv callbacks. Closing the stream here leads to SEND/RECV + * errors in other places that then overwrite the transfer's result. */ if(!stream->xfer_result) { stream->xfer_result = Curl_xfer_write_resp(data, buf, blen, eos); /* If the transfer write is errored, we do not want any more data */ if(stream->xfer_result) { - CURL_TRC_CF(data, cf, "[%"FMT_PRId64"] error %d writing %zu bytes " - "of data", stream->id, stream->xfer_result, blen); + CURL_TRC_CF(data, cf, "[%" PRId64 "] error %d writing %zu bytes of data", + stream->id, stream->xfer_result, blen); + } + } +} + +static void cf_ngtcp2_stream_update_window(struct Curl_cfilter *cf, + struct Curl_easy *data, + struct h3_stream_ctx *stream) +{ + /* stream receive max window size for flow control. We can only + * grow it from the initial window size */ + uint64_t swin_max = data->progress.dl.rlimit.rate_per_step ? + data->progress.dl.rlimit.rate_per_step : H3_STREAM_WINDOW_SIZE_MAX; + if(swin_max > stream->window_size_max) { + struct cf_ngtcp2_ctx *ctx = cf->ctx; + int rc = ngtcp2_conn_extend_max_stream_offset(ctx->qconn, stream->id, + swin_max - stream->window_size_max); + if(rc) { + CURL_TRC_CF(data, cf, "[%" PRId64 "] extend_max_stream_offset to %" + PRIu64 " -> %s (%d)", + stream->id, swin_max, ngtcp2_strerror(rc), rc); + DEBUGASSERT(0); } + stream->window_size_max = swin_max; + } +} + +static void cf_ngtcp2_ack_stream(struct Curl_cfilter *cf, + struct Curl_easy *data, + struct h3_stream_ctx *stream) +{ + struct cf_ngtcp2_ctx *ctx = cf->ctx; + curl_off_t avail; + uint64_t ack_len = 0; + + /* How many byte to ack on the stream? */ + + /* how much does rate limiting allow us to acknowledge? */ + avail = Curl_rlimit_avail(&data->progress.dl.rlimit, + Curl_pgrs_now(data)); + if(avail == CURL_OFF_T_MAX) { /* no rate limit, ack all */ + ack_len = stream->download_unacked; + } + else if(avail > 0) { + ack_len = CURLMIN(stream->download_unacked, (uint64_t)avail); } + + if(ack_len) { + CURL_TRC_CF(data, cf, "[%" PRId64 "] ACK %" PRIu64 + "/%" PRIu64 " bytes of DATA", stream->id, + ack_len, stream->download_unacked); + ngtcp2_conn_extend_max_stream_offset(ctx->qconn, stream->id, ack_len); + stream->download_unacked -= ack_len; + } + + cf_ngtcp2_stream_update_window(cf, data, stream); } static int cb_h3_recv_data(nghttp3_conn *conn, int64_t stream3_id, @@ -1061,13 +1116,15 @@ static int cb_h3_recv_data(nghttp3_conn *conn, int64_t stream3_id, return NGHTTP3_ERR_CALLBACK_FAILURE; h3_xfer_write_resp(cf, data, stream, (const char *)buf, blen, FALSE); - if(blen) { - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] ACK %zu bytes of DATA", - stream->id, blen); - ngtcp2_conn_extend_max_stream_offset(ctx->qconn, stream->id, blen); - ngtcp2_conn_extend_max_offset(ctx->qconn, blen); - } - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] DATA len=%zu", stream->id, blen); + CURL_TRC_CF(data, cf, "[%" PRId64 "] DATA len=%zu", stream->id, blen); + + ngtcp2_conn_extend_max_offset(ctx->qconn, blen); + if(UINT64_MAX - blen < stream->download_unacked) + stream->download_unacked = UINT64_MAX; /* unlikely */ + else + stream->download_unacked += blen; + + cf_ngtcp2_ack_stream(cf, data, stream); return 0; } @@ -1087,13 +1144,12 @@ static int cb_h3_deferred_consume(nghttp3_conn *conn, int64_t stream3_id, return 0; } -static int cb_h3_end_headers(nghttp3_conn *conn, int64_t sid, +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 cf_ngtcp2_ctx *ctx = cf->ctx; struct Curl_easy *data = stream_user_data; - curl_int64_t stream_id = (curl_int64_t)sid; struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); (void)conn; (void)stream_id; @@ -1105,7 +1161,7 @@ static int cb_h3_end_headers(nghttp3_conn *conn, int64_t sid, /* add a CRLF only if we have received some headers */ h3_xfer_write_resp_hd(cf, data, stream, STRCONST("\r\n"), stream->closed); - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] end_headers, status=%d", + 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; @@ -1114,14 +1170,13 @@ static int cb_h3_end_headers(nghttp3_conn *conn, int64_t sid, return 0; } -static int cb_h3_recv_header(nghttp3_conn *conn, int64_t sid, +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; struct cf_ngtcp2_ctx *ctx = cf->ctx; - curl_int64_t stream_id = (curl_int64_t)sid; nghttp3_vec h3name = nghttp3_rcbuf_get_buf(name); nghttp3_vec h3val = nghttp3_rcbuf_get_buf(value); struct Curl_easy *data = stream_user_data; @@ -1153,7 +1208,7 @@ static int cb_h3_recv_header(nghttp3_conn *conn, int64_t sid, if(!result) h3_xfer_write_resp_hd(cf, data, stream, curlx_dyn_ptr(&ctx->scratch), curlx_dyn_len(&ctx->scratch), FALSE); - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] status: %s", + CURL_TRC_CF(data, cf, "[%" PRId64 "] status: %s", stream_id, curlx_dyn_ptr(&ctx->scratch)); if(result) { return NGHTTP3_ERR_CALLBACK_FAILURE; @@ -1161,7 +1216,7 @@ static int cb_h3_recv_header(nghttp3_conn *conn, int64_t sid, } else { /* store as an HTTP1-style header */ - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] header: %.*s: %.*s", + CURL_TRC_CF(data, cf, "[%" PRId64 "] header: %.*s: %.*s", stream_id, (int)h3name.len, h3name.base, (int)h3val.len, h3val.base); curlx_dyn_reset(&ctx->scratch); @@ -1200,12 +1255,12 @@ static int cb_h3_stop_sending(nghttp3_conn *conn, int64_t stream_id, return 0; } -static int cb_h3_reset_stream(nghttp3_conn *conn, int64_t sid, +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) { + void *stream_user_data) +{ struct Curl_cfilter *cf = user_data; struct cf_ngtcp2_ctx *ctx = cf->ctx; - curl_int64_t stream_id = (curl_int64_t)sid; struct Curl_easy *data = stream_user_data; int rv; (void)conn; @@ -1213,7 +1268,7 @@ static int cb_h3_reset_stream(nghttp3_conn *conn, int64_t sid, rv = ngtcp2_conn_shutdown_stream_write(ctx->qconn, 0, stream_id, app_error_code); - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] reset -> %d", stream_id, rv); + CURL_TRC_CF(data, cf, "[%" PRId64 "] reset -> %d", stream_id, rv); if(rv && rv != NGTCP2_ERR_STREAM_NOT_FOUND) { return NGHTTP3_ERR_CALLBACK_FAILURE; } @@ -1307,32 +1362,25 @@ static CURLcode init_ngh3_conn(struct Curl_cfilter *cf, return CURLE_OK; } -static ssize_t recv_closed_stream(struct Curl_cfilter *cf, - struct Curl_easy *data, - struct h3_stream_ctx *stream, - CURLcode *err) +static CURLcode recv_closed_stream(struct Curl_cfilter *cf, + struct Curl_easy *data, + struct h3_stream_ctx *stream, + size_t *pnread) { - ssize_t nread = -1; - (void)cf; + *pnread = 0; if(stream->reset) { - failf(data, "HTTP/3 stream %" FMT_PRId64 " reset by server", stream->id); - *err = data->req.bytecount ? CURLE_PARTIAL_FILE : CURLE_HTTP3; - goto out; + failf(data, "HTTP/3 stream %" PRId64 " reset by server", stream->id); + return data->req.bytecount ? CURLE_PARTIAL_FILE : CURLE_HTTP3; } else if(!stream->resp_hds_complete) { failf(data, - "HTTP/3 stream %" FMT_PRId64 " was closed cleanly, but before " + "HTTP/3 stream %" PRId64 " was closed cleanly, but before " "getting all response header fields, treated as error", stream->id); - *err = CURLE_HTTP3; - goto out; + return CURLE_HTTP3; } - *err = CURLE_OK; - nread = 0; - -out: - return nread; + return CURLE_OK; } /* incoming data frames on the h3 stream */ @@ -1368,21 +1416,21 @@ static CURLcode cf_ngtcp2_recv(struct Curl_cfilter *cf, struct Curl_easy *data, goto out; } + cf_ngtcp2_ack_stream(cf, data, stream); + if(cf_progress_ingress(cf, data, &pktx)) { result = CURLE_RECV_ERROR; goto out; } if(stream->xfer_result) { - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] xfer write failed", stream->id); + CURL_TRC_CF(data, cf, "[%" PRId64 "] xfer write failed", stream->id); cf_ngtcp2_stream_close(cf, data, stream); result = stream->xfer_result; goto out; } else if(stream->closed) { - ssize_t nread = recv_closed_stream(cf, data, stream, &result); - if(nread > 0) - *pnread = (size_t)nread; + result = recv_closed_stream(cf, data, stream, pnread); goto out; } result = CURLE_AGAIN; @@ -1391,7 +1439,7 @@ static CURLcode cf_ngtcp2_recv(struct Curl_cfilter *cf, struct Curl_easy *data, result = Curl_1st_err(result, cf_progress_egress(cf, data, &pktx)); result = Curl_1st_err(result, check_and_set_expiry(cf, data, &pktx)); denied: - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] cf_recv(blen=%zu) -> %d, %zu", + CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_recv(blen=%zu) -> %d, %zu", stream ? stream->id : -1, blen, result, *pnread); CF_DATA_RESTORE(cf, save); return result; @@ -1430,11 +1478,10 @@ static int cb_h3_acked_req_body(nghttp3_conn *conn, int64_t stream_id, 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) +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 cf_ngtcp2_ctx *ctx = cf->ctx; @@ -1482,12 +1529,11 @@ cb_h3_read_req_body(nghttp3_conn *conn, int64_t stream_id, } else if(!nwritten) { /* Not EOF, and nothing to give, we signal WOULDBLOCK. */ - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] read req body -> AGAIN", - stream->id); + CURL_TRC_CF(data, cf, "[%" PRId64 "] read req body -> AGAIN", stream->id); return NGHTTP3_ERR_WOULDBLOCK; } - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] read req body -> " + CURL_TRC_CF(data, cf, "[%" PRId64 "] read req body -> " "%d vecs%s with %zu (buffered=%zu, left=%" FMT_OFF_T ")", stream->id, (int)nvecs, *pflags == NGHTTP3_DATA_FLAG_EOF ? " EOF" : "", @@ -1498,7 +1544,7 @@ cb_h3_read_req_body(nghttp3_conn *conn, int64_t stream_id, static CURLcode h3_stream_open(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, + const uint8_t *buf, size_t len, size_t *pnwritten) { struct cf_ngtcp2_ctx *ctx = cf->ctx; @@ -1509,7 +1555,6 @@ static CURLcode h3_stream_open(struct Curl_cfilter *cf, nghttp3_nv *nva = NULL; int rc = 0; unsigned int i; - ssize_t nwritten = -1; nghttp3_data_reader reader; nghttp3_data_reader *preader = NULL; CURLcode result; @@ -1527,10 +1572,12 @@ static CURLcode h3_stream_open(struct Curl_cfilter *cf, goto out; } - nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, &result); - if(nwritten < 0) + result = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, + !data->state.http_ignorecustom ? + data->set.str[STRING_CUSTOMREQUEST] : NULL, + 0, pnwritten); + if(result) goto out; - *pnwritten = (size_t)nwritten; if(!stream->h1.done) { /* need more data */ @@ -1546,7 +1593,7 @@ static CURLcode h3_stream_open(struct Curl_cfilter *cf, Curl_h1_req_parse_free(&stream->h1); nheader = Curl_dynhds_count(&h2_headers); - nva = malloc(sizeof(nghttp3_nv) * nheader); + nva = curlx_malloc(sizeof(nghttp3_nv) * nheader); if(!nva) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -1567,7 +1614,7 @@ static CURLcode h3_stream_open(struct Curl_cfilter *cf, result = CURLE_SEND_ERROR; goto out; } - stream->id = (curl_int64_t)sid; + stream->id = sid; ++ctx->used_bidi_streams; switch(data->state.httpreq) { @@ -1599,11 +1646,11 @@ static CURLcode h3_stream_open(struct Curl_cfilter *cf, if(rc) { switch(rc) { case NGHTTP3_ERR_CONN_CLOSING: - CURL_TRC_CF(data, cf, "h3sid[%" FMT_PRId64 "] failed to send, " + CURL_TRC_CF(data, cf, "h3sid[%" PRId64 "] failed to send, " "connection is closing", stream->id); break; default: - CURL_TRC_CF(data, cf, "h3sid[%" FMT_PRId64 "] failed to send -> " + CURL_TRC_CF(data, cf, "h3sid[%" PRId64 "] failed to send -> " "%d (%s)", stream->id, rc, nghttp3_strerror(rc)); break; } @@ -1612,24 +1659,26 @@ static CURLcode h3_stream_open(struct Curl_cfilter *cf, goto out; } + cf_ngtcp2_stream_update_window(cf, data, stream); + if(Curl_trc_is_verbose(data)) { - infof(data, "[HTTP/3] [%" FMT_PRId64 "] OPENED stream for %s", - stream->id, data->state.url); + infof(data, "[HTTP/3] [%" PRId64 "] OPENED stream for %s", + stream->id, Curl_bufref_ptr(&data->state.url)); for(i = 0; i < nheader; ++i) { - infof(data, "[HTTP/3] [%" FMT_PRId64 "] [%.*s: %.*s]", stream->id, + infof(data, "[HTTP/3] [%" PRId64 "] [%.*s: %.*s]", stream->id, (int)nva[i].namelen, nva[i].name, (int)nva[i].valuelen, nva[i].value); } } out: - free(nva); + curlx_free(nva); Curl_dynhds_free(&h2_headers); return result; } static CURLcode cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, bool eos, + const uint8_t *buf, size_t len, bool eos, size_t *pnwritten) { struct cf_ngtcp2_ctx *ctx = cf->ctx; @@ -1670,7 +1719,7 @@ static CURLcode cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data, stream = H3_STREAM_CTX(ctx, data); } else if(stream->xfer_result) { - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] xfer write failed", stream->id); + CURL_TRC_CF(data, cf, "[%" PRId64 "] xfer write failed", stream->id); cf_ngtcp2_stream_close(cf, data, stream); result = stream->xfer_result; goto out; @@ -1682,13 +1731,13 @@ static CURLcode cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data, * 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, "[%" FMT_PRId64 "] discarding data" + CURL_TRC_CF(data, cf, "[%" PRId64 "] discarding data" "on closed stream with response", stream->id); result = CURLE_OK; *pnwritten = len; goto out; } - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] send_body(len=%zu) " + CURL_TRC_CF(data, cf, "[%" PRId64 "] send_body(len=%zu) " "-> stream closed", stream->id, len); result = CURLE_HTTP3; goto out; @@ -1700,7 +1749,7 @@ static CURLcode cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data, } else { result = Curl_bufq_write(&stream->sendbuf, buf, len, pnwritten); - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] cf_send, add to " + CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_send, add to " "sendbuf(len=%zu) -> %d, %zu", stream->id, len, result, *pnwritten); if(result) @@ -1717,43 +1766,61 @@ static CURLcode cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data, out: result = Curl_1st_err(result, check_and_set_expiry(cf, data, &pktx)); denied: - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] cf_send(len=%zu) -> %d, %zu", + CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_send(len=%zu) -> %d, %zu", stream ? stream->id : -1, len, result, *pnwritten); CF_DATA_RESTORE(cf, save); return result; } -static CURLcode recv_pkt(const unsigned char *pkt, size_t pktlen, - struct sockaddr_storage *remote_addr, - socklen_t remote_addrlen, int ecn, - void *userp) +struct cf_ngtcp2_recv_ctx { + struct pkt_io_ctx *pktx; + size_t pkt_count; +}; + +static CURLcode cf_ngtcp2_recv_pkts(const unsigned char *buf, size_t buflen, + size_t gso_size, + struct sockaddr_storage *remote_addr, + socklen_t remote_addrlen, int ecn, + void *userp) { - struct pkt_io_ctx *pktx = userp; + struct cf_ngtcp2_recv_ctx *rctx = userp; + struct pkt_io_ctx *pktx = rctx->pktx; struct cf_ngtcp2_ctx *ctx = pktx->cf->ctx; ngtcp2_pkt_info pi; ngtcp2_path path; + size_t offset, pktlen; int rv; + if(!rctx->pkt_count) { + pktx_update_time(pktx->data, pktx, pktx->cf); + ngtcp2_path_storage_zero(&pktx->ps); + } + if(ecn) - CURL_TRC_CF(pktx->data, pktx->cf, "vquic_recv(len=%zu, ecn=%x)", - pktlen, ecn); + CURL_TRC_CF(pktx->data, pktx->cf, "vquic_recv(len=%zu, gso=%zu, ecn=%x)", + buflen, gso_size, ecn); ngtcp2_addr_init(&path.local, (struct sockaddr *)&ctx->q.local_addr, (socklen_t)ctx->q.local_addrlen); ngtcp2_addr_init(&path.remote, (struct sockaddr *)remote_addr, remote_addrlen); pi.ecn = (uint8_t)ecn; - 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 (%d)", - ngtcp2_strerror(rv), rv); - cf_ngtcp2_err_set(pktx->cf, pktx->data, rv); - - if(rv == NGTCP2_ERR_CRYPTO) - /* this is a "TLS problem", but a failed certificate verification - is a common reason for this */ - return CURLE_PEER_FAILED_VERIFICATION; - return CURLE_RECV_ERROR; + for(offset = 0; offset < buflen; offset += gso_size) { + rctx->pkt_count++; + pktlen = ((offset + gso_size) <= buflen) ? gso_size : (buflen - offset); + rv = ngtcp2_conn_read_pkt(ctx->qconn, &path, &pi, + buf + offset, pktlen, pktx->ts); + if(rv) { + CURL_TRC_CF(pktx->data, pktx->cf, "ingress, read_pkt -> %s (%d)", + ngtcp2_strerror(rv), rv); + cf_ngtcp2_err_set(pktx->cf, pktx->data, rv); + + if(rv == NGTCP2_ERR_CRYPTO) + /* this is a "TLS problem", but a failed certificate verification + is a common reason for this */ + return CURLE_PEER_FAILED_VERIFICATION; + return CURLE_RECV_ERROR; + } } return CURLE_OK; } @@ -1764,22 +1831,22 @@ static CURLcode cf_progress_ingress(struct Curl_cfilter *cf, { struct cf_ngtcp2_ctx *ctx = cf->ctx; struct pkt_io_ctx local_pktx; + struct cf_ngtcp2_recv_ctx rctx; CURLcode result = CURLE_OK; if(!pktx) { pktx_init(&local_pktx, cf, data); pktx = &local_pktx; } - else { - pktx_update_time(pktx, cf); - ngtcp2_path_storage_zero(&pktx->ps); - } result = Curl_vquic_tls_before_recv(&ctx->tls, cf, data); if(result) return result; - return vquic_recv_packets(cf, data, &ctx->q, 1000, recv_pkt, pktx); + rctx.pktx = pktx; + rctx.pkt_count = 0; + return vquic_recv_packets(cf, data, &ctx->q, 1000, + cf_ngtcp2_recv_pkts, &rctx); } /** @@ -1841,8 +1908,8 @@ static CURLcode read_pkt_to_send(void *userp, struct h3_stream_ctx *stream; DEBUGASSERT(ndatalen == -1); nghttp3_conn_block_stream(ctx->h3conn, stream_id); - CURL_TRC_CF(x->data, x->cf, "[%" FMT_PRId64 "] block quic flow", - (curl_int64_t)stream_id); + CURL_TRC_CF(x->data, x->cf, "[%" PRId64 "] block quic flow", + stream_id); stream = cf_ngtcp2_get_stream(ctx, stream_id); if(stream) /* it might be not one of our h3 streams? */ stream->quic_flow_blocked = TRUE; @@ -1873,7 +1940,7 @@ static CURLcode read_pkt_to_send(void *userp, /* we add the amount of data bytes to the flow windows */ int rv = nghttp3_conn_add_write_offset(ctx->h3conn, stream_id, ndatalen); if(rv) { - failf(x->data, "nghttp3_conn_add_write_offset returned error: %s\n", + failf(x->data, "nghttp3_conn_add_write_offset returned error: %s", nghttp3_strerror(rv)); return CURLE_SEND_ERROR; } @@ -1905,7 +1972,7 @@ static CURLcode cf_progress_egress(struct Curl_cfilter *cf, pktx = &local_pktx; } else { - pktx_update_time(pktx, cf); + pktx_update_time(data, pktx, cf); ngtcp2_path_storage_zero(&pktx->ps); } @@ -1931,7 +1998,7 @@ static CURLcode cf_progress_egress(struct Curl_cfilter *cf, */ max_payload_size = ngtcp2_conn_get_max_tx_udp_payload_size(ctx->qconn); path_max_payload_size = - ngtcp2_conn_get_path_max_tx_udp_payload_size(ctx->qconn); + ngtcp2_conn_get_path_max_tx_udp_payload_size(ctx->qconn); send_quantum = ngtcp2_conn_get_send_quantum(ctx->qconn); CURL_TRC_CF(data, cf, "egress, collect and send packets, quantum=%zu", send_quantum); @@ -1947,7 +2014,7 @@ static CURLcode cf_progress_egress(struct Curl_cfilter *cf, size_t buflen = Curl_bufq_len(&ctx->q.sendbuf); if((buflen >= send_quantum) || ((buflen + gsolen) >= ctx->q.sendbuf.chunk_size)) - break; + break; DEBUGASSERT(nread > 0); ++pktcnt; if(pktcnt == 1) { @@ -1992,7 +2059,7 @@ static CURLcode cf_progress_egress(struct Curl_cfilter *cf, } return curlcode; } - pktx_update_time(pktx, cf); + pktx_update_time(data, pktx, cf); ngtcp2_conn_update_pkt_tx_time(ctx->qconn, pktx->ts); } return CURLE_OK; @@ -2126,8 +2193,8 @@ static CURLcode cf_ngtcp2_shutdown(struct Curl_cfilter *cf, (uint8_t *)buffer, sizeof(buffer), &ctx->last_error, pktx.ts); CURL_TRC_CF(data, cf, "start shutdown(err_type=%d, err_code=%" - FMT_PRIu64 ") -> %d", ctx->last_error.type, - (curl_uint64_t)ctx->last_error.error_code, (int)nwritten); + PRIu64 ") -> %d", ctx->last_error.type, + ctx->last_error.error_code, (int)nwritten); /* there are cases listed in ngtcp2 documentation where this call * may fail. Since we are doing a connection shutdown as graceful * as we can, such an error is ignored here. */ @@ -2243,7 +2310,6 @@ static int quic_ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) #endif Curl_ossl_add_session(cf, data, ctx->peer.scache_key, ssl_sessionid, SSL_version(ssl), "h3", quic_tp, quic_tp_len); - return 1; } return 0; } @@ -2254,16 +2320,26 @@ static int quic_ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) static const char *gtls_hs_msg_name(int mtype) { switch(mtype) { - case 1: return "ClientHello"; - case 2: return "ServerHello"; - case 4: return "SessionTicket"; - case 8: return "EncryptedExtensions"; - case 11: return "Certificate"; - case 13: return "CertificateRequest"; - case 15: return "CertificateVerify"; - case 20: return "Finished"; - case 24: return "KeyUpdate"; - case 254: return "MessageHash"; + case 1: + return "ClientHello"; + case 2: + return "ServerHello"; + case 4: + return "SessionTicket"; + case 8: + return "EncryptedExtensions"; + case 11: + return "Certificate"; + case 13: + return "CertificateRequest"; + case 15: + return "CertificateVerify"; + case 20: + return "Finished"; + case 24: + return "KeyUpdate"; + case 254: + return "MessageHash"; } return "Unknown"; } @@ -2353,7 +2429,6 @@ static CURLcode cf_ngtcp2_tls_ctx_setup(struct Curl_cfilter *cf, void *user_data) { struct curl_tls_ctx *ctx = user_data; - struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); #ifdef USE_OPENSSL #if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC) @@ -2370,7 +2445,7 @@ static CURLcode cf_ngtcp2_tls_ctx_setup(struct Curl_cfilter *cf, return CURLE_FAILED_INIT; } #endif /* !OPENSSL_IS_BORINGSSL && !OPENSSL_IS_AWSLC */ - if(ssl_config->primary.cache_session) { + if(Curl_ssl_scache_use(cf, data)) { /* Enable the session cache because it is a prerequisite for the * "new session" callback. Use the "external storage" mode to prevent * OpenSSL from creating an internal session cache. @@ -2386,7 +2461,7 @@ static CURLcode cf_ngtcp2_tls_ctx_setup(struct Curl_cfilter *cf, failf(data, "ngtcp2_crypto_gnutls_configure_client_session failed"); return CURLE_FAILED_INIT; } - if(ssl_config->primary.cache_session) { + if(Curl_ssl_scache_use(cf, data)) { gnutls_handshake_set_hook_function(ctx->gtls.session, GNUTLS_HANDSHAKE_ANY, GNUTLS_HOOK_POST, quic_gtls_handshake_cb); @@ -2397,7 +2472,7 @@ static CURLcode cf_ngtcp2_tls_ctx_setup(struct Curl_cfilter *cf, failf(data, "ngtcp2_crypto_wolfssl_configure_client_context failed"); return CURLE_FAILED_INIT; } - if(ssl_config->primary.cache_session) { + if(Curl_ssl_scache_use(cf, data)) { /* Register to get notified when a new session is received */ wolfSSL_CTX_sess_set_new_cb(ctx->wssl.ssl_ctx, wssl_quic_new_session_cb); } @@ -2430,7 +2505,7 @@ static CURLcode cf_ngtcp2_on_session_reuse(struct Curl_cfilter *cf, #endif /* WOLFSSL_EARLY_DATA */ #endif #if defined(USE_GNUTLS) || defined(USE_WOLFSSL) || \ - (defined(USE_OPENSSL) && defined(HAVE_OPENSSL_EARLYDATA)) + (defined(USE_OPENSSL) && defined(HAVE_OPENSSL_EARLYDATA)) if((!ctx->earlydata_max)) { CURL_TRC_CF(data, cf, "SSL session does not allow earlydata"); } @@ -2480,7 +2555,7 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf, CURLcode result; const struct Curl_sockaddr_ex *sockaddr = NULL; int qfd; - static const struct alpn_spec ALPN_SPEC_H3 = {{ "h3", "h3-29" }, 2}; + static const struct alpn_spec ALPN_SPEC_H3 = { { "h3", "h3-29" }, 2 }; DEBUGASSERT(ctx->initialized); ctx->dcid.datalen = NGTCP2_MAX_CIDLEN; @@ -2497,7 +2572,7 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf, ctx->qlogfd = qfd; /* -1 if failure above */ quic_settings(ctx, data, pktx); - result = vquic_ctx_init(&ctx->q); + result = vquic_ctx_init(data, &ctx->q); if(result) return result; @@ -2566,7 +2641,6 @@ static CURLcode cf_ngtcp2_connect(struct Curl_cfilter *cf, struct cf_ngtcp2_ctx *ctx = cf->ctx; CURLcode result = CURLE_OK; struct cf_call_data save; - struct curltime now; struct pkt_io_ctx pktx; if(cf->connected) { @@ -2582,13 +2656,12 @@ static CURLcode cf_ngtcp2_connect(struct Curl_cfilter *cf, } *done = FALSE; - now = curlx_now(); pktx_init(&pktx, cf, data); CF_DATA_SAVE(save, cf, data); if(!ctx->qconn) { - ctx->started_at = now; + ctx->started_at = *Curl_pgrs_now(data); result = cf_connect_start(cf, data, &pktx); if(result) goto out; @@ -2615,7 +2688,6 @@ static CURLcode cf_ngtcp2_connect(struct Curl_cfilter *cf, CURL_TRC_CF(data, cf, "peer verified"); cf->connected = TRUE; *done = TRUE; - connkeep(cf->conn, "HTTP/3 default"); } } @@ -2626,9 +2698,8 @@ static CURLcode cf_ngtcp2_connect(struct Curl_cfilter *cf, result = CURLE_COULDNT_CONNECT; if(cerr) { - CURL_TRC_CF(data, cf, "connect error, type=%d, code=%" - FMT_PRIu64, - cerr->type, (curl_uint64_t)cerr->error_code); + CURL_TRC_CF(data, cf, "connect error, type=%d, code=%" PRIu64, + cerr->type, cerr->error_code); switch(cerr->type) { case NGTCP2_CCERR_TYPE_VERSION_NEGOTIATION: CURL_TRC_CF(data, cf, "error in version negotiation"); @@ -2642,7 +2713,7 @@ static CURLcode cf_ngtcp2_connect(struct Curl_cfilter *cf, CURL_TRC_CF(data, cf, "connection refused by server"); /* When a QUIC server instance is shutting down, it may send us a * CONNECTION_CLOSE with this code right away. We want - * to keep on trying in this case. */ + * to keep on trying in this case. */ result = CURLE_WEIRD_SERVER_REPLY; } } @@ -2687,7 +2758,7 @@ static CURLcode cf_ngtcp2_query(struct Curl_cfilter *cf, } else if(ctx->max_bidi_streams) { uint64_t avail_bidi_streams = 0; - uint64_t max_streams = CONN_ATTACHED(cf->conn); + uint64_t max_streams = cf->conn->attached_xfers; if(ctx->max_bidi_streams > ctx->used_bidi_streams) avail_bidi_streams = ctx->max_bidi_streams - ctx->used_bidi_streams; max_streams += avail_bidi_streams; @@ -2697,13 +2768,14 @@ static CURLcode cf_ngtcp2_query(struct Curl_cfilter *cf, *pres1 = (int)Curl_multi_max_concurrent_streams(data->multi); CURL_TRC_CF(data, cf, "query conn[%" FMT_OFF_T "]: " "MAX_CONCURRENT -> %d (%u in use)", - cf->conn->connection_id, *pres1, CONN_ATTACHED(cf->conn)); + cf->conn->connection_id, *pres1, cf->conn->attached_xfers); CF_DATA_RESTORE(cf, save); return CURLE_OK; } case CF_QUERY_CONNECT_REPLY_MS: if(ctx->q.got_first_byte) { - timediff_t ms = curlx_timediff(ctx->q.first_byte_at, ctx->started_at); + timediff_t ms = curlx_ptimediff_ms(&ctx->q.first_byte_at, + &ctx->started_at); *pres1 = (ms < INT_MAX) ? (int)ms : INT_MAX; } else @@ -2764,7 +2836,8 @@ static bool cf_ngtcp2_conn_is_alive(struct Curl_cfilter *cf, * it will close the connection when it expires. */ rp = ngtcp2_conn_get_remote_transport_params(ctx->qconn); if(rp && rp->max_idle_timeout) { - timediff_t idletime_ms = curlx_timediff(curlx_now(), ctx->q.last_io); + timediff_t idletime_ms = + curlx_ptimediff_ms(Curl_pgrs_now(data), &ctx->q.last_io); if(idletime_ms > 0) { uint64_t max_idle_ms = (uint64_t)(rp->max_idle_timeout / NGTCP2_MILLISECONDS); @@ -2821,7 +2894,7 @@ CURLcode Curl_cf_ngtcp2_create(struct Curl_cfilter **pcf, CURLcode result; (void)data; - ctx = calloc(1, sizeof(*ctx)); + ctx = curlx_calloc(1, sizeof(*ctx)); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -2850,20 +2923,4 @@ CURLcode Curl_cf_ngtcp2_create(struct Curl_cfilter **pcf, return result; } -bool Curl_conn_is_ngtcp2(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; -} - #endif diff --git a/lib/vquic/curl_ngtcp2.h b/lib/vquic/curl_ngtcp2.h index 86753a3a6ba8..7933e924e1c7 100644 --- a/lib/vquic/curl_ngtcp2.h +++ b/lib/vquic/curl_ngtcp2.h @@ -55,10 +55,6 @@ CURLcode Curl_cf_ngtcp2_create(struct Curl_cfilter **pcf, struct Curl_easy *data, struct connectdata *conn, const struct Curl_addrinfo *ai); - -bool Curl_conn_is_ngtcp2(const struct Curl_easy *data, - const struct connectdata *conn, - int sockindex); #endif #endif /* HEADER_CURL_VQUIC_CURL_NGTCP2_H */ diff --git a/lib/vquic/curl_osslq.c b/lib/vquic/curl_osslq.c index a49074346270..cffe61a4022d 100644 --- a/lib/vquic/curl_osslq.c +++ b/lib/vquic/curl_osslq.c @@ -33,10 +33,7 @@ #include #include "../urldata.h" -#include "../hash.h" -#include "../sendf.h" -#include "../strdup.h" -#include "../rand.h" +#include "../curl_trc.h" #include "../multiif.h" #include "../cfilters.h" #include "../cf-socket.h" @@ -45,7 +42,6 @@ #include "../curlx/dynbuf.h" #include "../http1.h" #include "../select.h" -#include "../curlx/inet_pton.h" #include "../uint-hash.h" #include "vquic.h" #include "vquic_int.h" @@ -55,12 +51,9 @@ #include "../vtls/openssl.h" #include "curl_osslq.h" #include "../url.h" -#include "../curlx/warnless.h" +#include "../bufref.h" #include "../curlx/strerr.h" - -/* The last 2 #include files should be in this order */ -#include "../curl_memory.h" -#include "../memdebug.h" +#include "../curlx/strcopy.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 @@ -74,13 +67,13 @@ * spares. 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 + (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) + (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE) #define H3_STREAM_SEND_CHUNKS \ - (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE) + (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE) #if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC) typedef uint32_t sslerr_t; @@ -91,8 +84,7 @@ typedef unsigned long sslerr_t; /* 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 +#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); @@ -150,7 +142,7 @@ static char *osslq_strerror(unsigned long error, char *buf, size_t size) if(!*buf) { const char *msg = error ? "Unknown error" : "No error"; if(strlen(msg) < size) - strcpy(buf, msg); + curlx_strcopy(buf, size, msg, strlen(msg)); } return buf; @@ -208,7 +200,7 @@ static CURLcode make_bio_addr(BIO_ADDR **pbio_addr, /* QUIC stream (not necessarily H3) */ struct cf_osslq_stream { - curl_int64_t id; + int64_t id; SSL *ssl; struct bufq recvbuf; /* QUIC war data recv buffer */ BIT(recvd_eos); @@ -229,7 +221,7 @@ static CURLcode cf_osslq_stream_open(struct cf_osslq_stream *s, if(!s->ssl) { return CURLE_FAILED_INIT; } - s->id = (curl_int64_t)SSL_get_stream_id(s->ssl); + s->id = SSL_get_stream_id(s->ssl); SSL_set_app_data(s->ssl, user_data); return CURLE_OK; } @@ -306,7 +298,7 @@ static void cf_osslq_ctx_init(struct cf_osslq_ctx *ctx) DEBUGASSERT(!ctx->initialized); Curl_bufcp_init(&ctx->stream_bufcp, H3_STREAM_CHUNK_SIZE, H3_STREAM_POOL_SPARES); - Curl_uint_hash_init(&ctx->streams, 63, h3_stream_hash_free); + Curl_uint32_hash_init(&ctx->streams, 63, h3_stream_hash_free); ctx->poll_items = NULL; ctx->curl_items = NULL; ctx->items_max = 0; @@ -317,12 +309,12 @@ static void cf_osslq_ctx_free(struct cf_osslq_ctx *ctx) { if(ctx && ctx->initialized) { Curl_bufcp_free(&ctx->stream_bufcp); - Curl_uint_hash_destroy(&ctx->streams); + Curl_uint32_hash_destroy(&ctx->streams); Curl_ssl_peer_cleanup(&ctx->peer); - free(ctx->poll_items); - free(ctx->curl_items); + curlx_free(ctx->poll_items); + curlx_free(ctx->curl_items); } - free(ctx); + curlx_free(ctx); } static void cf_osslq_ctx_close(struct cf_osslq_ctx *ctx) @@ -451,36 +443,36 @@ static CURLcode cf_osslq_h3conn_add_stream(struct cf_osslq_h3conn *h3, struct Curl_easy *data) { struct cf_osslq_ctx *ctx = cf->ctx; - curl_int64_t stream_id = (curl_int64_t)SSL_get_stream_id(stream_ssl); + int64_t stream_id = (int64_t)SSL_get_stream_id(stream_ssl); int stype = SSL_get_stream_type(stream_ssl); /* This could be a GREASE stream, e.g. HTTP/3 rfc9114 ch 6.2.3 * reserved stream type that is supposed to be discarded silently. * BUT OpenSSL does not offer this information to us. So, we silently * ignore all such streams we do not expect. */ switch(stype) { - case SSL_STREAM_TYPE_READ: { - struct cf_osslq_stream *nstream; - if(h3->remote_ctrl_n >= CURL_ARRAYSIZE(h3->remote_ctrl)) { - /* rejected, we are full */ - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] reject remote uni stream", - stream_id); - SSL_free(stream_ssl); - return CURLE_OK; - } - 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, "[%" FMT_PRId64 "] accepted remote uni stream", + case SSL_STREAM_TYPE_READ: { + struct cf_osslq_stream *nstream; + if(h3->remote_ctrl_n >= CURL_ARRAYSIZE(h3->remote_ctrl)) { + /* rejected, we are full */ + CURL_TRC_CF(data, cf, "[%" PRId64 "] reject remote uni stream", stream_id); - return CURLE_OK; - } - default: - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] reject remote %s" - " stream, type=%x", stream_id, - (stype == SSL_STREAM_TYPE_BIDI) ? "bidi" : "write", stype); SSL_free(stream_ssl); return CURLE_OK; + } + 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 remote uni stream", + stream_id); + return CURLE_OK; + } + default: + CURL_TRC_CF(data, cf, "[%" PRId64 "] reject remote %s" + " stream, type=%x", stream_id, + (stype == SSL_STREAM_TYPE_BIDI) ? "bidi" : "write", stype); + SSL_free(stream_ssl); + return CURLE_OK; } } @@ -510,8 +502,7 @@ static CURLcode cf_osslq_ssl_err(struct Curl_cfilter *cf, lerr = SSL_get_verify_result(ctx->tls.ossl.ssl); if(lerr != X509_V_OK) { ssl_config->certverifyresult = lerr; - curl_msnprintf(ebuf, sizeof(ebuf), - "SSL certificate problem: %s", + curl_msnprintf(ebuf, sizeof(ebuf), "SSL certificate problem: %s", X509_verify_cert_error_string(lerr)); } else @@ -545,7 +536,7 @@ static CURLcode cf_osslq_ssl_err(struct Curl_cfilter *cf, * the SO_ERROR is also lost. */ if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) { - char extramsg[80]=""; + char extramsg[80] = ""; int sockerr = SOCKERRNO; struct ip_quadruple ip; @@ -575,20 +566,21 @@ static CURLcode cf_osslq_verify_peer(struct Curl_cfilter *cf, */ 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 */ + 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 recv_buf_nonflow; /* buffered bytes, not counting for flow control */ - curl_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 */ - BIT(resp_hds_complete); /* we have a complete, final response */ - BIT(closed); /* TRUE on stream close */ - BIT(reset); /* TRUE on stream reset */ - BIT(send_closed); /* stream is local closed */ - BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */ + 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 */ + BIT(resp_hds_complete); /* we have a complete, final response */ + BIT(closed); /* TRUE on stream close */ + BIT(reset); /* TRUE on stream reset */ + BIT(send_closed); /* stream is local closed */ + BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */ }; static void h3_stream_ctx_free(struct h3_stream_ctx *stream) @@ -597,7 +589,7 @@ static void h3_stream_ctx_free(struct h3_stream_ctx *stream) Curl_bufq_free(&stream->sendbuf); Curl_bufq_free(&stream->recvbuf); Curl_h1_req_parse_free(&stream->h1); - free(stream); + curlx_free(stream); } static void h3_stream_hash_free(unsigned int id, void *stream) @@ -619,7 +611,7 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf, if(stream) return CURLE_OK; - stream = calloc(1, sizeof(*stream)); + stream = curlx_calloc(1, sizeof(*stream)); if(!stream) return CURLE_OUT_OF_MEMORY; @@ -635,7 +627,7 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf, stream->recv_buf_nonflow = 0; Curl_h1_req_parse_init(&stream->h1, H1_PARSE_DEFAULT_MAX_LINE_LEN); - if(!Curl_uint_hash_set(&ctx->streams, data->mid, stream)) { + if(!Curl_uint32_hash_set(&ctx->streams, data->mid, stream)) { h3_stream_ctx_free(stream); return CURLE_OUT_OF_MEMORY; } @@ -650,8 +642,7 @@ static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data) (void)cf; if(stream) { - CURL_TRC_CF(data, cf, "[%"FMT_PRId64"] easy handle is done", - stream->s.id); + CURL_TRC_CF(data, cf, "[%" PRIu64 "] easy handle is done", stream->s.id); if(ctx->h3.conn && (stream->s.id >= 0) && !stream->closed) { nghttp3_conn_shutdown_stream_read(ctx->h3.conn, stream->s.id); nghttp3_conn_close_stream(ctx->h3.conn, stream->s.id, @@ -660,16 +651,16 @@ static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data) stream->closed = TRUE; } - Curl_uint_hash_remove(&ctx->streams, data->mid); + Curl_uint32_hash_remove(&ctx->streams, data->mid); } } struct cf_ossq_find_ctx { - curl_int64_t stream_id; + int64_t stream_id; struct h3_stream_ctx *stream; }; -static bool cf_osslq_find_stream(unsigned int mid, void *val, void *user_data) +static bool cf_osslq_find_stream(uint32_t mid, void *val, void *user_data) { struct h3_stream_ctx *stream = val; struct cf_ossq_find_ctx *fctx = user_data; @@ -705,7 +696,7 @@ static struct cf_osslq_stream *cf_osslq_get_qstream(struct Curl_cfilter *cf, struct cf_ossq_find_ctx fctx; fctx.stream_id = stream_id; fctx.stream = NULL; - Curl_uint_hash_visit(&ctx->streams, cf_osslq_find_stream, &fctx); + Curl_uint32_hash_visit(&ctx->streams, cf_osslq_find_stream, &fctx); if(fctx.stream) return &fctx.stream->s; } @@ -744,11 +735,11 @@ static int cb_h3_stream_close(nghttp3_conn *conn, int64_t stream_id, if(stream->error3 != NGHTTP3_H3_NO_ERROR) { stream->reset = TRUE; stream->send_closed = TRUE; - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] RESET: error %" FMT_PRIu64, + CURL_TRC_CF(data, cf, "[%" PRId64 "] RESET: error %" PRIu64, stream->s.id, stream->error3); } else { - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] CLOSED", stream->s.id); + CURL_TRC_CF(data, cf, "[%" PRId64 "] CLOSED", stream->s.id); } Curl_multi_mark_dirty(data); return 0; @@ -778,11 +769,11 @@ static CURLcode write_resp_raw(struct Curl_cfilter *cf, return result; if(!flow) - stream->recv_buf_nonflow += (size_t)nwritten; + stream->recv_buf_nonflow += nwritten; if(nwritten < memlen) { /* This MUST not happen. Our recbuf is dimensioned to hold the - * full max_stream_window and then some for this very reason. */ + * full max_stream_window and then some for this reason. */ DEBUGASSERT(0); return CURLE_RECV_ERROR; } @@ -807,12 +798,12 @@ static int cb_h3_recv_data(nghttp3_conn *conn, int64_t stream3_id, result = write_resp_raw(cf, data, buf, buflen, TRUE); if(result) { - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] DATA len=%zu, ERROR %d", + CURL_TRC_CF(data, cf, "[%" PRId64 "] DATA len=%zu, ERROR %d", stream->s.id, buflen, result); return NGHTTP3_ERR_CALLBACK_FAILURE; } stream->download_recvd += (curl_off_t)buflen; - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] DATA len=%zu, total=%" FMT_OFF_T, + CURL_TRC_CF(data, cf, "[%" PRId64 "] DATA len=%zu, total=%" FMT_OFF_T, stream->s.id, buflen, stream->download_recvd); Curl_multi_mark_dirty(data); return 0; @@ -830,18 +821,17 @@ static int cb_h3_deferred_consume(nghttp3_conn *conn, int64_t stream_id, (void)conn; (void)stream_id; if(stream) - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] deferred consume %zu bytes", + 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 sid, +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; - curl_int64_t stream_id = sid; struct cf_osslq_ctx *ctx = cf->ctx; nghttp3_vec h3name = nghttp3_rcbuf_get_buf(name); nghttp3_vec h3val = nghttp3_rcbuf_get_buf(value); @@ -868,7 +858,7 @@ static int cb_h3_recv_header(nghttp3_conn *conn, int64_t sid, return -1; ncopy = curl_msnprintf(line, sizeof(line), "HTTP/3 %03d \r\n", stream->status_code); - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] status: %s", stream_id, line); + CURL_TRC_CF(data, cf, "[%" PRId64 "] status: %s", stream_id, line); result = write_resp_raw(cf, data, line, ncopy, FALSE); if(result) { return -1; @@ -876,7 +866,7 @@ static int cb_h3_recv_header(nghttp3_conn *conn, int64_t sid, } else { /* store as an HTTP1-style header */ - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] header: %.*s: %.*s", + 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); @@ -899,13 +889,12 @@ static int cb_h3_recv_header(nghttp3_conn *conn, int64_t sid, return 0; } -static int cb_h3_end_headers(nghttp3_conn *conn, int64_t sid, +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 cf_osslq_ctx *ctx = cf->ctx; struct Curl_easy *data = stream_user_data; - curl_int64_t stream_id = sid; struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); CURLcode result = CURLE_OK; (void)conn; @@ -921,7 +910,7 @@ static int cb_h3_end_headers(nghttp3_conn *conn, int64_t sid, return -1; } - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] end_headers, status=%d", + 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; @@ -930,14 +919,13 @@ static int cb_h3_end_headers(nghttp3_conn *conn, int64_t sid, return 0; } -static int cb_h3_stop_sending(nghttp3_conn *conn, int64_t sid, +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 cf_osslq_ctx *ctx = cf->ctx; struct Curl_easy *data = stream_user_data; - curl_int64_t stream_id = sid; struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); (void)conn; (void)app_error_code; @@ -945,27 +933,27 @@ static int cb_h3_stop_sending(nghttp3_conn *conn, int64_t sid, if(!stream || !stream->s.ssl) return 0; - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] stop_sending", stream_id); + 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 sid, +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) { + void *stream_user_data) +{ struct Curl_cfilter *cf = user_data; struct cf_osslq_ctx *ctx = cf->ctx; struct Curl_easy *data = stream_user_data; - curl_int64_t stream_id = sid; struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); int rv; (void)conn; if(stream && stream->s.ssl) { - SSL_STREAM_RESET_ARGS args = {0}; + 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, "[%" FMT_PRId64 "] reset -> %d", stream_id, rv); + CURL_TRC_CF(data, cf, "[%" PRId64 "] reset -> %d", stream_id, rv); if(!rv) { return NGHTTP3_ERR_CALLBACK_FAILURE; } @@ -973,11 +961,10 @@ static int cb_h3_reset_stream(nghttp3_conn *conn, int64_t sid, 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) +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 cf_osslq_ctx *ctx = cf->ctx; @@ -1025,12 +1012,12 @@ cb_h3_read_req_body(nghttp3_conn *conn, int64_t stream_id, } else if(!nwritten) { /* Not EOF, and nothing to give, we signal WOULDBLOCK. */ - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] read req body -> AGAIN", + CURL_TRC_CF(data, cf, "[%" PRId64 "] read req body -> AGAIN", stream->s.id); return NGHTTP3_ERR_WOULDBLOCK; } - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] read req body -> " + CURL_TRC_CF(data, cf, "[%" PRId64 "] read req body -> " "%d vecs%s with %zu (buffered=%zu, left=%" FMT_OFF_T ")", stream->s.id, (int)nvecs, *pflags == NGHTTP3_DATA_FLAG_EOF ? " EOF" : "", @@ -1114,21 +1101,21 @@ static CURLcode cf_osslq_h3conn_init(struct cf_osslq_ctx *ctx, SSL *conn, } result = cf_osslq_stream_open(&h3->s_ctrl, conn, - SSL_STREAM_FLAG_ADVANCE|SSL_STREAM_FLAG_UNI, + 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, + 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, + SSL_STREAM_FLAG_ADVANCE | SSL_STREAM_FLAG_UNI, &ctx->stream_bufcp, NULL); if(result) { result = CURLE_QUIC_CONNECT_ERROR; @@ -1171,7 +1158,7 @@ static CURLcode cf_osslq_ctx_start(struct Curl_cfilter *cf, if(result) goto out; - result = vquic_ctx_init(&ctx->q); + result = vquic_ctx_init(data, &ctx->q); if(result) goto out; @@ -1229,7 +1216,8 @@ static CURLcode cf_osslq_ctx_start(struct Curl_cfilter *cf, SSL_INCOMING_STREAM_POLICY_ACCEPT, 0); /* from our side, there is no idle timeout */ SSL_set_value_uint(ctx->tls.ossl.ssl, - SSL_VALUE_CLASS_FEATURE_REQUEST, SSL_VALUE_QUIC_IDLE_TIMEOUT, 0); + SSL_VALUE_CLASS_FEATURE_REQUEST, + SSL_VALUE_QUIC_IDLE_TIMEOUT, 0); /* setup the H3 things on top of the QUIC connection */ result = cf_osslq_h3conn_init(ctx, ctx->tls.ossl.ssl, cf); @@ -1262,7 +1250,7 @@ static CURLcode h3_quic_recv(void *reader_ctx, return CURLE_AGAIN; } else if(detail == SSL_ERROR_ZERO_RETURN) { - CURL_TRC_CF(x->data, x->cf, "[%" FMT_PRId64 "] h3_quic_recv -> EOS", + CURL_TRC_CF(x->data, x->cf, "[%" PRId64 "] h3_quic_recv -> EOS", x->s->id); x->s->recvd_eos = TRUE; return CURLE_OK; @@ -1275,9 +1263,9 @@ static CURLcode h3_quic_recv(void *reader_ctx, return CURLE_RECV_ERROR; } else { - CURL_TRC_CF(x->data, x->cf, "[%" FMT_PRId64 "] h3_quic_recv -> RESET, " - "rv=%d, app_err=%" FMT_PRIu64, - x->s->id, rv, (curl_uint64_t)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; } @@ -1332,7 +1320,7 @@ static CURLcode cf_osslq_stream_recv(struct cf_osslq_stream *s, 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, "[%" FMT_PRId64 "] forward %zu bytes " + 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", @@ -1372,7 +1360,7 @@ static CURLcode cf_osslq_stream_recv(struct cf_osslq_stream *s, rv = nghttp3_conn_close_stream(ctx->h3.conn, s->id, NGHTTP3_H3_NO_ERROR); s->closed = TRUE; - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] close nghttp3 stream -> %d", + 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", @@ -1385,7 +1373,7 @@ static CURLcode cf_osslq_stream_recv(struct cf_osslq_stream *s, } out: if(result) - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] cf_osslq_stream_recv -> %d", + CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_osslq_stream_recv -> %d", s->id, result); return result; } @@ -1396,7 +1384,7 @@ struct cf_ossq_recv_ctx { CURLcode result; }; -static bool cf_osslq_iter_recv(unsigned int mid, void *val, void *user_data) +static bool cf_osslq_iter_recv(uint32_t mid, void *val, void *user_data) { struct h3_stream_ctx *stream = val; struct cf_ossq_recv_ctx *rctx = user_data; @@ -1459,7 +1447,7 @@ static CURLcode cf_progress_ingress(struct Curl_cfilter *cf, rctx.cf = cf; rctx.multi = data->multi; rctx.result = CURLE_OK; - Curl_uint_hash_visit(&ctx->streams, cf_osslq_iter_recv, &rctx); + Curl_uint32_hash_visit(&ctx->streams, cf_osslq_iter_recv, &rctx); result = rctx.result; } @@ -1474,7 +1462,7 @@ struct cf_ossq_fill_ctx { size_t n; }; -static bool cf_osslq_collect_block_send(unsigned int mid, void *val, +static bool cf_osslq_collect_block_send(uint32_t mid, void *val, void *user_data) { struct h3_stream_ctx *stream = val; @@ -1512,21 +1500,22 @@ static CURLcode cf_osslq_check_and_unblock(struct Curl_cfilter *cf, if(ctx->h3.conn) { struct cf_ossq_fill_ctx fill_ctx; - if(ctx->items_max < Curl_uint_hash_count(&ctx->streams)) { - size_t nmax = Curl_uint_hash_count(&ctx->streams); + if(ctx->items_max < Curl_uint32_hash_count(&ctx->streams)) { + size_t nmax = Curl_uint32_hash_count(&ctx->streams); ctx->items_max = 0; - tmpptr = realloc(ctx->poll_items, nmax * sizeof(SSL_POLL_ITEM)); + tmpptr = curlx_realloc(ctx->poll_items, nmax * sizeof(SSL_POLL_ITEM)); if(!tmpptr) { - free(ctx->poll_items); + curlx_free(ctx->poll_items); ctx->poll_items = NULL; res = CURLE_OUT_OF_MEMORY; goto out; } ctx->poll_items = tmpptr; - tmpptr = realloc(ctx->curl_items, nmax * sizeof(struct Curl_easy *)); + tmpptr = curlx_realloc(ctx->curl_items, + nmax * sizeof(struct Curl_easy *)); if(!tmpptr) { - free(ctx->curl_items); + curlx_free(ctx->curl_items); ctx->curl_items = NULL; res = CURLE_OUT_OF_MEMORY; goto out; @@ -1538,8 +1527,8 @@ static CURLcode cf_osslq_check_and_unblock(struct Curl_cfilter *cf, fill_ctx.ctx = ctx; fill_ctx.multi = data->multi; fill_ctx.n = 0; - Curl_uint_hash_visit(&ctx->streams, cf_osslq_collect_block_send, - &fill_ctx); + Curl_uint32_hash_visit(&ctx->streams, cf_osslq_collect_block_send, + &fill_ctx); poll_count = fill_ctx.n; if(poll_count) { CURL_TRC_CF(data, cf, "polling %zu blocked streams", poll_count); @@ -1548,7 +1537,7 @@ static CURLcode cf_osslq_check_and_unblock(struct Curl_cfilter *cf, res = CURLE_UNRECOVERABLE_POLL; if(!SSL_poll(ctx->poll_items, poll_count, sizeof(SSL_POLL_ITEM), &timeout, 0, &result_count)) - goto out; + goto out; res = CURLE_OK; @@ -1609,7 +1598,7 @@ static CURLcode h3_send_streams(struct Curl_cfilter *cf, s = cf_osslq_get_qstream(cf, data, stream_id); if(!s) { failf(data, "nghttp3_conn_writev_stream gave unknown stream %" - FMT_PRId64, (curl_int64_t)stream_id); + PRId64, stream_id); result = CURLE_SEND_ERROR; goto out; } @@ -1624,13 +1613,13 @@ static CURLcode h3_send_streams(struct Curl_cfilter *cf, uint64_t flags = (eos && ((i + 1) == n)) ? SSL_WRITE_FLAG_CONCLUDE : 0; written = vec[i].len; ok = !s->ssl || SSL_write_ex2(s->ssl, vec[i].base, vec[i].len, flags, - &written); + &written); if(ok && flags & SSL_WRITE_FLAG_CONCLUDE) eos_written = TRUE; if(ok) { /* As OpenSSL buffers the data, we count this as acknowledged * from nghttp3's point of view */ - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] send %zu bytes to QUIC ok", + CURL_TRC_CF(data, cf, "[%" PRId64 "] send %zu bytes to QUIC ok", s->id, vec[i].len); acked_len += vec[i].len; } @@ -1640,14 +1629,14 @@ static CURLcode h3_send_streams(struct Curl_cfilter *cf, case SSL_ERROR_WANT_WRITE: case SSL_ERROR_WANT_READ: /* QUIC blocked us from writing more */ - CURL_TRC_CF(data, cf, "[%"FMT_PRId64 "] send %zu bytes to " + 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, "[%"FMT_PRId64 "] send %zu bytes to QUIC, SSL error %d", + 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_HTTP3); goto out; @@ -1658,28 +1647,28 @@ static CURLcode h3_send_streams(struct Curl_cfilter *cf, 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 */ - ctx->q.last_io = curlx_now(); + ctx->q.last_io = *Curl_pgrs_now(data); 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", + failf(data, "nghttp3_conn_add_write_offset returned error: %s", 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", + failf(data, "nghttp3_conn_add_ack_offset returned error: %s", nghttp3_strerror(rv)); result = CURLE_SEND_ERROR; goto out; } - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] forwarded %zu/%zu h3 bytes " + 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 && !eos_written) { /* wrote everything and H3 indicates end of stream */ - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] closing QUIC stream", s->id); + CURL_TRC_CF(data, cf, "[%" PRId64 "] closing QUIC stream", s->id); SSL_stream_conclude(s->ssl, 0); } } @@ -1756,7 +1745,6 @@ static CURLcode cf_osslq_connect(struct Curl_cfilter *cf, struct cf_osslq_ctx *ctx = cf->ctx; CURLcode result = CURLE_OK; struct cf_call_data save; - struct curltime now; int err; if(cf->connected) { @@ -1772,11 +1760,10 @@ static CURLcode cf_osslq_connect(struct Curl_cfilter *cf, } *done = FALSE; - now = curlx_now(); CF_DATA_SAVE(save, cf, data); if(!ctx->tls.ossl.ssl) { - ctx->started_at = now; + ctx->started_at = *Curl_pgrs_now(data); result = cf_osslq_ctx_start(cf, data); if(result) goto out; @@ -1786,7 +1773,7 @@ static CURLcode cf_osslq_connect(struct Curl_cfilter *cf, int readable = SOCKET_READABLE(ctx->q.sockfd, 0); if(readable > 0 && (readable & CURL_CSELECT_IN)) { ctx->got_first_byte = TRUE; - ctx->first_byte_at = curlx_now(); + ctx->first_byte_at = *Curl_pgrs_now(data); } } @@ -1803,33 +1790,39 @@ static CURLcode cf_osslq_connect(struct Curl_cfilter *cf, if(err == 1) { /* connected */ - ctx->handshake_at = now; - ctx->q.last_io = now; - CURL_TRC_CF(data, cf, "handshake complete after %dms", - (int)curlx_timediff(now, ctx->started_at)); + if(!ctx->got_first_byte) { + /* if not recorded yet, take the timestamp before we called + * SSL_do_handshake() as the time we received the first packet. */ + ctx->got_first_byte = TRUE; + ctx->first_byte_at = *Curl_pgrs_now(data); + } + /* Record the handshake complete with a new time stamp. */ + ctx->handshake_at = *Curl_pgrs_now(data); + ctx->q.last_io = *Curl_pgrs_now(data); + CURL_TRC_CF(data, cf, "handshake complete after %" FMT_TIMEDIFF_T "ms", + curlx_ptimediff_ms(Curl_pgrs_now(data), &ctx->started_at)); result = cf_osslq_verify_peer(cf, data); if(!result) { CURL_TRC_CF(data, cf, "peer verified"); cf->connected = TRUE; *done = TRUE; - connkeep(cf->conn, "HTTP/3 default"); } } else { int detail = SSL_get_error(ctx->tls.ossl.ssl, err); switch(detail) { case SSL_ERROR_WANT_READ: - ctx->q.last_io = now; + ctx->q.last_io = *Curl_pgrs_now(data); CURL_TRC_CF(data, cf, "QUIC SSL_connect() -> WANT_RECV"); goto out; case SSL_ERROR_WANT_WRITE: - ctx->q.last_io = now; + ctx->q.last_io = *Curl_pgrs_now(data); 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: - ctx->q.last_io = now; + ctx->q.last_io = *Curl_pgrs_now(data); CURL_TRC_CF(data, cf, "QUIC SSL_connect() -> WANT_ASYNC"); result = CURLE_OK; goto out; @@ -1872,10 +1865,10 @@ static CURLcode cf_osslq_connect(struct Curl_cfilter *cf, return result; } -static ssize_t h3_stream_open(struct Curl_cfilter *cf, - struct Curl_easy *data, - const void *buf, size_t len, - CURLcode *err) +static CURLcode h3_stream_open(struct Curl_cfilter *cf, + struct Curl_easy *data, + const uint8_t *buf, size_t len, + size_t *pnwritten) { struct cf_osslq_ctx *ctx = cf->ctx; struct h3_stream_ctx *stream = NULL; @@ -1884,24 +1877,27 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf, nghttp3_nv *nva = NULL; int rc = 0; unsigned int i; - ssize_t nwritten = -1; nghttp3_data_reader reader; nghttp3_data_reader *preader = NULL; + CURLcode result; Curl_dynhds_init(&h2_headers, 0, DYN_HTTP_REQUEST); - *err = h3_data_setup(cf, data); - if(*err) + result = h3_data_setup(cf, data); + if(result) goto out; stream = H3_STREAM_CTX(ctx, data); DEBUGASSERT(stream); if(!stream) { - *err = CURLE_FAILED_INIT; + result = CURLE_FAILED_INIT; goto out; } - nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, 0, err); - if(nwritten < 0) + result = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL, + !data->state.http_ignorecustom ? + data->set.str[STRING_CUSTOMREQUEST] : NULL, + 0, pnwritten); + if(result) goto out; if(!stream->h1.done) { /* need more data */ @@ -1909,19 +1905,16 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf, } DEBUGASSERT(stream->h1.req); - *err = Curl_http_req_to_h2(&h2_headers, stream->h1.req, data); - if(*err) { - nwritten = -1; + result = Curl_http_req_to_h2(&h2_headers, stream->h1.req, data); + if(result) goto out; - } /* no longer needed */ Curl_h1_req_parse_free(&stream->h1); nheader = Curl_dynhds_count(&h2_headers); - nva = malloc(sizeof(nghttp3_nv) * nheader); + nva = curlx_malloc(sizeof(nghttp3_nv) * nheader); if(!nva) { - *err = CURLE_OUT_OF_MEMORY; - nwritten = -1; + result = CURLE_OUT_OF_MEMORY; goto out; } @@ -1935,11 +1928,11 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf, } DEBUGASSERT(stream->s.id == -1); - *err = cf_osslq_stream_open(&stream->s, ctx->tls.ossl.ssl, 0, - &ctx->stream_bufcp, data); - if(*err) { + result = cf_osslq_stream_open(&stream->s, ctx->tls.ossl.ssl, 0, + &ctx->stream_bufcp, data); + if(result) { failf(data, "cannot get bidi streams"); - *err = CURLE_SEND_ERROR; + result = CURLE_SEND_ERROR; goto out; } @@ -1972,24 +1965,23 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf, if(rc) { switch(rc) { case NGHTTP3_ERR_CONN_CLOSING: - CURL_TRC_CF(data, cf, "h3sid[%"FMT_PRId64"] failed to send, " + CURL_TRC_CF(data, cf, "h3sid[%" PRId64 "] failed to send, " "connection is closing", stream->s.id); break; default: - CURL_TRC_CF(data, cf, "h3sid[%"FMT_PRId64 "] failed to send -> %d (%s)", + 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; + result = CURLE_SEND_ERROR; goto out; } if(Curl_trc_is_verbose(data)) { - infof(data, "[HTTP/3] [%" FMT_PRId64 "] OPENED stream for %s", - stream->s.id, data->state.url); + infof(data, "[HTTP/3] [%" PRId64 "] OPENED stream for %s", + stream->s.id, Curl_bufref_ptr(&data->state.url)); for(i = 0; i < nheader; ++i) { - infof(data, "[HTTP/3] [%" FMT_PRId64 "] [%.*s: %.*s]", + infof(data, "[HTTP/3] [%" PRId64 "] [%.*s: %.*s]", stream->s.id, (int)nva[i].namelen, nva[i].name, (int)nva[i].valuelen, nva[i].value); @@ -1997,19 +1989,18 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf, } out: - free(nva); + curlx_free(nva); Curl_dynhds_free(&h2_headers); - return nwritten; + return result; } static CURLcode cf_osslq_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, bool eos, + const uint8_t *buf, size_t len, bool eos, size_t *pnwritten) { struct cf_osslq_ctx *ctx = cf->ctx; - struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); + struct h3_stream_ctx *stream = NULL; struct cf_call_data save; - ssize_t nwritten; CURLcode result = CURLE_OK; (void)eos; /* use to end stream */ @@ -2027,14 +2018,14 @@ static CURLcode cf_osslq_send(struct Curl_cfilter *cf, struct Curl_easy *data, if(result) goto out; + stream = H3_STREAM_CTX(ctx, data); if(!stream || stream->s.id < 0) { - nwritten = h3_stream_open(cf, data, buf, len, &result); - if(nwritten < 0) { + result = h3_stream_open(cf, data, buf, len, pnwritten); + if(result) { CURL_TRC_CF(data, cf, "failed to open stream -> %d", result); goto out; } stream = H3_STREAM_CTX(ctx, data); - *pnwritten = (size_t)nwritten; } else if(stream->closed) { if(stream->resp_hds_complete) { @@ -2043,20 +2034,20 @@ static CURLcode cf_osslq_send(struct Curl_cfilter *cf, struct Curl_easy *data, * 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, "[%" FMT_PRId64 "] discarding data" + CURL_TRC_CF(data, cf, "[%" PRId64 "] discarding data" "on closed stream with response", stream->s.id); result = CURLE_OK; *pnwritten = len; goto out; } - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] send_body(len=%zu) " + CURL_TRC_CF(data, cf, "[%" PRId64 "] send_body(len=%zu) " "-> stream closed", stream->s.id, len); result = CURLE_HTTP3; goto out; } else { result = Curl_bufq_write(&stream->sendbuf, buf, len, pnwritten); - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] cf_send, add to " + CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_send, add to " "sendbuf(len=%zu) -> %d, %zu", stream->s.id, len, result, *pnwritten); if(result) @@ -2069,7 +2060,7 @@ static CURLcode cf_osslq_send(struct Curl_cfilter *cf, struct Curl_easy *data, out: result = Curl_1st_err(result, check_and_set_expiry(cf, data)); - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] cf_send(len=%zu) -> %d, %zu", + CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_send(len=%zu) -> %d, %zu", stream ? stream->s.id : -1, len, result, *pnwritten); CF_DATA_RESTORE(cf, save); return result; @@ -2084,13 +2075,13 @@ static CURLcode recv_closed_stream(struct Curl_cfilter *cf, *pnread = 0; if(stream->reset) { failf(data, - "HTTP/3 stream %" FMT_PRId64 " reset by server", + "HTTP/3 stream %" PRId64 " reset by server", stream->s.id); return data->req.bytecount ? CURLE_PARTIAL_FILE : CURLE_HTTP3; } else if(!stream->resp_hds_complete) { failf(data, - "HTTP/3 stream %" FMT_PRId64 + "HTTP/3 stream %" PRId64 " was closed cleanly, but before getting" " all response header fields, treated as error", stream->s.id); @@ -2103,18 +2094,17 @@ static CURLcode cf_osslq_recv(struct Curl_cfilter *cf, struct Curl_easy *data, char *buf, size_t len, size_t *pnread) { struct cf_osslq_ctx *ctx = cf->ctx; - struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); + struct h3_stream_ctx *stream; struct cf_call_data save; CURLcode result = CURLE_OK; - (void)ctx; CF_DATA_SAVE(save, cf, data); DEBUGASSERT(cf->connected); - DEBUGASSERT(ctx); DEBUGASSERT(ctx->tls.ossl.ssl); DEBUGASSERT(ctx->h3.conn); *pnread = 0; + stream = H3_STREAM_CTX(ctx, data); if(!stream) { result = CURLE_RECV_ERROR; goto out; @@ -2123,8 +2113,8 @@ static CURLcode cf_osslq_recv(struct Curl_cfilter *cf, struct Curl_easy *data, if(!Curl_bufq_is_empty(&stream->recvbuf)) { result = Curl_bufq_cread(&stream->recvbuf, buf, len, pnread); if(result) { - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] read recvbuf(len=%zu) " - "-> %d, %zu", stream->s.id, len, result, *pnread); + CURL_TRC_CF(data, cf, "[%" PRId64 "] read recvbuf(len=%zu) -> %d, %zu", + stream->s.id, len, result, *pnread); goto out; } } @@ -2137,8 +2127,8 @@ static CURLcode cf_osslq_recv(struct Curl_cfilter *cf, struct Curl_easy *data, if(!*pnread && !Curl_bufq_is_empty(&stream->recvbuf)) { result = Curl_bufq_cread(&stream->recvbuf, buf, len, pnread); if(result) { - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] read recvbuf(len=%zu) " - "-> %d, %zu", stream->s.id, len, result, *pnread); + CURL_TRC_CF(data, cf, "[%" PRId64 "] read recvbuf(len=%zu) -> %d, %zu", + stream->s.id, len, result, *pnread); goto out; } } @@ -2158,7 +2148,7 @@ static CURLcode cf_osslq_recv(struct Curl_cfilter *cf, struct Curl_easy *data, result = Curl_1st_err(result, cf_progress_egress(cf, data)); result = Curl_1st_err(result, check_and_set_expiry(cf, data)); - CURL_TRC_CF(data, cf, "[%" FMT_PRId64 "] cf_recv(len=%zu) -> %d, %zu", + CURL_TRC_CF(data, cf, "[%" PRId64 "] cf_recv(len=%zu) -> %d, %zu", stream ? stream->s.id : -1, len, result, *pnread); CF_DATA_RESTORE(cf, save); return result; @@ -2245,9 +2235,8 @@ static bool cf_osslq_conn_is_alive(struct Curl_cfilter *cf, "assume connection is dead."); goto out; } - CURL_TRC_CF(data, cf, "negotiated idle timeout: %" FMT_PRIu64 "ms", - (curl_uint64_t)idle_ms); - idletime = curlx_timediff(curlx_now(), ctx->q.last_io); + CURL_TRC_CF(data, cf, "negotiated idle timeout: %" PRIu64 "ms", idle_ms); + idletime = curlx_ptimediff_ms(Curl_pgrs_now(data), &ctx->q.last_io); if(idle_ms && idletime > 0 && (uint64_t)idletime > idle_ms) goto out; } @@ -2327,7 +2316,7 @@ static CURLcode cf_osslq_query(struct Curl_cfilter *cf, return CURLE_HTTP3; } /* we report avail + in_use */ - v += CONN_ATTACHED(cf->conn); + v += cf->conn->attached_xfers; *pres1 = (v > INT_MAX) ? INT_MAX : (int)v; #else *pres1 = 100; @@ -2337,7 +2326,8 @@ static CURLcode cf_osslq_query(struct Curl_cfilter *cf, } case CF_QUERY_CONNECT_REPLY_MS: if(ctx->got_first_byte) { - timediff_t ms = curlx_timediff(ctx->first_byte_at, ctx->started_at); + timediff_t ms = curlx_ptimediff_ms(&ctx->first_byte_at, + &ctx->started_at); *pres1 = (ms < INT_MAX) ? (int)ms : INT_MAX; } else @@ -2408,7 +2398,7 @@ CURLcode Curl_cf_osslq_create(struct Curl_cfilter **pcf, CURLcode result; (void)data; - ctx = calloc(1, sizeof(*ctx)); + ctx = curlx_calloc(1, sizeof(*ctx)); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; diff --git a/lib/vquic/curl_quiche.c b/lib/vquic/curl_quiche.c index 55f6e79ebefc..c85336cd02d7 100644 --- a/lib/vquic/curl_quiche.c +++ b/lib/vquic/curl_quiche.c @@ -33,8 +33,7 @@ #include "../urldata.h" #include "../cfilters.h" #include "../cf-socket.h" -#include "../sendf.h" -#include "../strdup.h" +#include "../curl_trc.h" #include "../rand.h" #include "../multiif.h" #include "../connect.h" @@ -47,15 +46,11 @@ #include "curl_quiche.h" #include "../transfer.h" #include "../url.h" -#include "../curlx/inet_pton.h" +#include "../bufref.h" #include "../vtls/openssl.h" #include "../vtls/keylog.h" #include "../vtls/vtls.h" -/* The last 2 #include files should be in this order */ -#include "../curl_memory.h" -#include "../memdebug.h" - /* HTTP/3 error values defined in RFC 9114, ch. 8.1 */ #define CURL_H3_NO_ERROR (0x0100) @@ -68,11 +63,11 @@ * stream buffer to not keep spares. 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 + (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) + (H3_STREAM_WINDOW_SIZE / H3_STREAM_CHUNK_SIZE) /* * Store quiche version info in this buffer. @@ -93,8 +88,9 @@ struct cf_quiche_ctx { uint8_t scid[QUICHE_MAX_CONN_ID_LEN]; struct curltime started_at; /* time the current attempt started */ struct curltime handshake_at; /* time connect handshake finished */ - struct bufc_pool stream_bufcp; /* chunk pool for streams */ struct uint_hash streams; /* hash `data->mid` to `stream_ctx` */ + struct dynbuf scratch; /* temp buffer for header construction */ + struct bufq writebuf; /* temp buffer for writing bodies */ curl_off_t data_recvd; BIT(initialized); BIT(goaway); /* got GOAWAY from server */ @@ -123,9 +119,10 @@ static void cf_quiche_ctx_init(struct cf_quiche_ctx *ctx) debug_log_init = 1; } #endif - Curl_bufcp_init(&ctx->stream_bufcp, H3_STREAM_CHUNK_SIZE, - H3_STREAM_POOL_SPARES); - Curl_uint_hash_init(&ctx->streams, 63, h3_stream_hash_free); + curlx_dyn_init(&ctx->scratch, CURL_MAX_HTTP_HEADER); + Curl_uint32_hash_init(&ctx->streams, 63, h3_stream_hash_free); + Curl_bufq_init2(&ctx->writebuf, H3_STREAM_CHUNK_SIZE, H3_STREAM_RECV_CHUNKS, + BUFQ_OPT_SOFT_LIMIT); ctx->data_recvd = 0; ctx->initialized = TRUE; } @@ -138,10 +135,11 @@ static void cf_quiche_ctx_free(struct cf_quiche_ctx *ctx) Curl_vquic_tls_cleanup(&ctx->tls); Curl_ssl_peer_cleanup(&ctx->peer); vquic_ctx_free(&ctx->q); - Curl_bufcp_free(&ctx->stream_bufcp); - Curl_uint_hash_destroy(&ctx->streams); + Curl_uint32_hash_destroy(&ctx->streams); + curlx_dyn_free(&ctx->scratch); + Curl_bufq_free(&ctx->writebuf); } - free(ctx); + curlx_free(ctx); } static void cf_quiche_ctx_close(struct cf_quiche_ctx *ctx) @@ -171,24 +169,24 @@ static CURLcode cf_flush_egress(struct Curl_cfilter *cf, * All about the H3 internals of a stream */ struct h3_stream_ctx { - curl_uint64_t id; /* HTTP/3 protocol stream identifier */ - struct bufq recvbuf; /* h3 response */ + uint64_t id; /* HTTP/3 protocol stream identifier */ struct h1_req_parser h1; /* h1 request parsing */ - curl_uint64_t error3; /* HTTP/3 stream error code */ - BIT(opened); /* TRUE after stream has been opened */ - BIT(closed); /* TRUE on stream close */ - BIT(reset); /* TRUE on stream reset */ - BIT(send_closed); /* stream is locally closed */ + uint64_t error3; /* HTTP/3 stream error code */ + int status_code; /* HTTP status code */ + CURLcode xfer_result; /* result from cf_quiche_write_(hd/body) */ + BIT(opened); /* TRUE after stream has been opened */ + BIT(closed); /* TRUE on stream close */ + BIT(reset); /* TRUE on stream reset */ + BIT(send_closed); /* stream is locally closed */ BIT(resp_hds_complete); /* final response has been received */ - BIT(resp_got_header); /* TRUE when h3 stream has recvd some HEADER */ - BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */ + BIT(resp_got_header); /* TRUE when h3 stream has recvd some HEADER */ + BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */ }; static void h3_stream_ctx_free(struct h3_stream_ctx *stream) { - Curl_bufq_free(&stream->recvbuf); Curl_h1_req_parse_free(&stream->h1); - free(stream); + curlx_free(stream); } static void h3_stream_hash_free(unsigned int id, void *stream) @@ -210,7 +208,7 @@ struct cf_quiche_visit_ctx { void *user_data; }; -static bool cf_quiche_stream_do(unsigned int mid, void *val, void *user_data) +static bool cf_quiche_stream_do(uint32_t mid, void *val, void *user_data) { struct cf_quiche_visit_ctx *vctx = user_data; struct h3_stream_ctx *stream = val; @@ -231,7 +229,7 @@ static void cf_quiche_for_all_streams(struct Curl_cfilter *cf, vctx.multi = multi; vctx.cb = do_cb; vctx.user_data = user_data; - Curl_uint_hash_visit(&ctx->streams, cf_quiche_stream_do, &vctx); + Curl_uint32_hash_visit(&ctx->streams, cf_quiche_stream_do, &vctx); } static bool cf_quiche_do_resume(struct Curl_cfilter *cf, @@ -243,7 +241,7 @@ static bool cf_quiche_do_resume(struct Curl_cfilter *cf, if(stream->quic_flow_blocked) { stream->quic_flow_blocked = FALSE; Curl_multi_mark_dirty(sdata); - CURL_TRC_CF(sdata, cf, "[%"FMT_PRIu64"] unblock", stream->id); + CURL_TRC_CF(sdata, cf, "[%" PRIu64 "] unblock", stream->id); } return TRUE; } @@ -256,6 +254,7 @@ static bool cf_quiche_do_expire(struct Curl_cfilter *cf, (void)stream; (void)user_data; CURL_TRC_CF(sdata, cf, "conn closed, mark as dirty"); + stream->xfer_result = CURLE_SEND_ERROR; Curl_multi_mark_dirty(sdata); return TRUE; } @@ -269,16 +268,14 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf, if(stream) return CURLE_OK; - stream = calloc(1, sizeof(*stream)); + stream = curlx_calloc(1, sizeof(*stream)); if(!stream) return CURLE_OUT_OF_MEMORY; stream->id = -1; - Curl_bufq_initp(&stream->recvbuf, &ctx->stream_bufcp, - H3_STREAM_RECV_CHUNKS, BUFQ_OPT_SOFT_LIMIT); Curl_h1_req_parse_init(&stream->h1, H1_PARSE_DEFAULT_MAX_LINE_LEN); - if(!Curl_uint_hash_set(&ctx->streams, data->mid, stream)) { + if(!Curl_uint32_hash_set(&ctx->streams, data->mid, stream)) { h3_stream_ctx_free(stream); return CURLE_OUT_OF_MEMORY; } @@ -286,29 +283,39 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf, return CURLE_OK; } +static void cf_quiche_stream_close(struct Curl_cfilter *cf, + struct Curl_easy *data, + struct h3_stream_ctx *stream) +{ + struct cf_quiche_ctx *ctx = cf->ctx; + CURLcode result; + + 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; + result = cf_flush_egress(cf, data); + if(result) + CURL_TRC_CF(data, cf, "[%" PRIu64 "] stream close, flush egress -> %d", + stream->id, result); + } +} + static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data) { struct cf_quiche_ctx *ctx = cf->ctx; struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); - CURLcode result; (void)cf; if(stream) { - CURL_TRC_CF(data, cf, "[%"FMT_PRIu64"] easy handle is done", stream->id); - 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; - result = cf_flush_egress(cf, data); - if(result) - CURL_TRC_CF(data, cf, "data_done, flush egress -> %d", result); - } - Curl_uint_hash_remove(&ctx->streams, data->mid); + CURL_TRC_CF(data, cf, "[%" PRIu64 "] easy handle is done", stream->id); + cf_quiche_stream_close(cf, data, stream); + Curl_uint32_hash_remove(&ctx->streams, data->mid); } } @@ -320,39 +327,29 @@ static void cf_quiche_expire_conn_closed(struct Curl_cfilter *cf, cf_quiche_for_all_streams(cf, data->multi, cf_quiche_do_expire, NULL); } -/* - * 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, +static void cf_quiche_write_hd(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *mem, size_t memlen) + struct h3_stream_ctx *stream, + const char *buf, size_t blen, bool eos) { - struct cf_quiche_ctx *ctx = cf->ctx; - struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); - CURLcode result = CURLE_OK; - size_t nwritten; - - (void)cf; - if(!stream) - return CURLE_RECV_ERROR; - result = Curl_bufq_write(&stream->recvbuf, mem, memlen, &nwritten); - if(result) - return result; - - if(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; + /* This function returns no error intentionally, but records + * the result at the stream, skipping further writes once the + * `result` of the transfer is known. + * The stream is subsequently cancelled "higher up" in the filter's + * send/recv callbacks. Closing the stream here leads to SEND/RECV + * errors in other places that then overwrite the transfer's result. */ + if(!stream->xfer_result) { + stream->xfer_result = Curl_xfer_write_resp_hd(data, buf, blen, eos); + if(stream->xfer_result) + CURL_TRC_CF(data, cf, "[%" PRId64 "] error %d writing %zu " + "bytes of headers", stream->id, stream->xfer_result, blen); } - return result; } struct cb_ctx { struct Curl_cfilter *cf; struct Curl_easy *data; + struct h3_stream_ctx *stream; }; static int cb_each_header(uint8_t *name, size_t name_len, @@ -360,39 +357,59 @@ static int cb_each_header(uint8_t *name, size_t name_len, void *argp) { struct cb_ctx *x = argp; - struct cf_quiche_ctx *ctx = x->cf->ctx; - struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, x->data); + struct Curl_cfilter *cf = x->cf; + struct Curl_easy *data = x->data; + struct h3_stream_ctx *stream = x->stream; + struct cf_quiche_ctx *ctx = cf->ctx; CURLcode result; - if(!stream) - return CURLE_OK; + if(!stream || stream->xfer_result) + return 1; /* abort iteration */ if((name_len == 7) && !strncmp(HTTP_PSEUDO_STATUS, (char *)name, 7)) { - CURL_TRC_CF(x->data, x->cf, "[%" FMT_PRIu64 "] status: %.*s", - stream->id, (int)value_len, value); - result = write_resp_raw(x->cf, x->data, "HTTP/3 ", sizeof("HTTP/3 ") - 1); + curlx_dyn_reset(&ctx->scratch); + result = Curl_http_decode_status(&stream->status_code, + (const char *)value, value_len); + if(!result) + result = curlx_dyn_addn(&ctx->scratch, STRCONST("HTTP/3 ")); + if(!result) + result = curlx_dyn_addn(&ctx->scratch, + (const char *)value, value_len); if(!result) - result = write_resp_raw(x->cf, x->data, value, value_len); + result = curlx_dyn_addn(&ctx->scratch, STRCONST(" \r\n")); if(!result) - result = write_resp_raw(x->cf, x->data, " \r\n", 3); + cf_quiche_write_hd(cf, data, stream, curlx_dyn_ptr(&ctx->scratch), + curlx_dyn_len(&ctx->scratch), FALSE); + CURL_TRC_CF(data, cf, "[%" PRId64 "] status: %s", + stream->id, curlx_dyn_ptr(&ctx->scratch)); } else { - CURL_TRC_CF(x->data, x->cf, "[%" FMT_PRIu64 "] header: %.*s: %.*s", + /* store as an HTTP1-style header */ + CURL_TRC_CF(data, cf, "[%" PRId64 "] header: %.*s: %.*s", stream->id, (int)name_len, name, (int)value_len, value); - result = write_resp_raw(x->cf, x->data, name, name_len); + curlx_dyn_reset(&ctx->scratch); + result = curlx_dyn_addn(&ctx->scratch, + (const char *)name, name_len); if(!result) - result = write_resp_raw(x->cf, x->data, ": ", 2); + result = curlx_dyn_addn(&ctx->scratch, STRCONST(": ")); if(!result) - result = write_resp_raw(x->cf, x->data, value, value_len); + result = curlx_dyn_addn(&ctx->scratch, + (const char *)value, value_len); if(!result) - result = write_resp_raw(x->cf, x->data, "\r\n", 2); + result = curlx_dyn_addn(&ctx->scratch, STRCONST("\r\n")); + if(!result) + cf_quiche_write_hd(cf, data, stream, curlx_dyn_ptr(&ctx->scratch), + curlx_dyn_len(&ctx->scratch), FALSE); } + if(result) { - CURL_TRC_CF(x->data, x->cf, "[%"FMT_PRIu64"] on header error %d", + CURL_TRC_CF(x->data, x->cf, "[%" PRIu64 "] on header error %d", stream->id, result); + if(!stream->xfer_result) + stream->xfer_result = result; } - return result; + return stream->xfer_result ? 1 : 0; } static CURLcode stream_resp_read(void *reader_ctx, @@ -409,160 +426,143 @@ static CURLcode stream_resp_read(void *reader_ctx, return CURLE_RECV_ERROR; nread = quiche_h3_recv_body(ctx->h3c, ctx->qconn, stream->id, buf, len); - if(nread >= 0) { - *pnread = (size_t)nread; - return CURLE_OK; - } - else + if(!curlx_sztouz(nread, pnread)) return CURLE_AGAIN; + return CURLE_OK; } -static CURLcode cf_recv_body(struct Curl_cfilter *cf, - struct Curl_easy *data) +static void cf_quiche_flush_body(struct Curl_cfilter *cf, + struct Curl_easy *data, + struct h3_stream_ctx *stream) +{ + struct cf_quiche_ctx *ctx = cf->ctx; + const uint8_t *buf; + size_t blen; + + while(stream && !stream->xfer_result) { + if(Curl_bufq_peek(&ctx->writebuf, &buf, &blen)) { + stream->xfer_result = Curl_xfer_write_resp( + data, (const char *)buf, blen, FALSE); + Curl_bufq_skip(&ctx->writebuf, blen); + if(stream->xfer_result) { + CURL_TRC_CF(data, cf, "[%" PRId64 "] error %d writing %zu bytes" + " of data", stream->id, stream->xfer_result, blen); + } + } + else + break; + } + Curl_bufq_reset(&ctx->writebuf); +} + +static void cf_quiche_recv_body(struct Curl_cfilter *cf, + struct Curl_easy *data, + struct h3_stream_ctx *stream) { struct cf_quiche_ctx *ctx = cf->ctx; - struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); size_t nread; struct cb_ctx cb_ctx; CURLcode result = CURLE_OK; if(!stream) - return CURLE_RECV_ERROR; - - if(!stream->resp_hds_complete) { - result = write_resp_raw(cf, data, "\r\n", 2); - if(result) - return result; - stream->resp_hds_complete = TRUE; - } + return; + /* Even when the transfer has already errored, we need to receive + * the data from quiche, as quiche will otherwise get stuck and + * raise events to receive over and over again. */ cb_ctx.cf = cf; cb_ctx.data = data; - result = Curl_bufq_slurp(&stream->recvbuf, - stream_resp_read, &cb_ctx, &nread); - - if(result && result != CURLE_AGAIN) { - CURL_TRC_CF(data, cf, "[%"FMT_PRIu64"] recv_body error %zu", - stream->id, nread); - failf(data, "Error %d in HTTP/3 response body for stream[%"FMT_PRIu64"]", - result, stream->id); - stream->closed = TRUE; - stream->reset = TRUE; - stream->send_closed = TRUE; - streamclose(cf->conn, "Reset of stream"); - return result; - } - return CURLE_OK; -} - -#ifdef DEBUGBUILD -static const char *cf_ev_name(quiche_h3_event *ev) -{ - switch(quiche_h3_event_type(ev)) { - case QUICHE_H3_EVENT_HEADERS: - return "HEADERS"; - case QUICHE_H3_EVENT_DATA: - return "DATA"; - case QUICHE_H3_EVENT_RESET: - return "RESET"; - case QUICHE_H3_EVENT_FINISHED: - return "FINISHED"; - case QUICHE_H3_EVENT_GOAWAY: - return "GOAWAY"; - default: - return "Unknown"; + cb_ctx.stream = stream; + Curl_bufq_reset(&ctx->writebuf); + while(!result) { + result = Curl_bufq_slurp(&ctx->writebuf, + stream_resp_read, &cb_ctx, &nread); + if(!result) + cf_quiche_flush_body(cf, data, stream); + else if(result == CURLE_AGAIN) + break; + else if(result) { + CURL_TRC_CF(data, cf, "[%" PRIu64 "] recv_body error %d", + stream->id, result); + failf(data, "[%" PRIu64 "] Error %d in HTTP/3 response body for stream", + stream->id, result); + stream->closed = TRUE; + stream->reset = TRUE; + stream->send_closed = TRUE; + if(!stream->xfer_result) + stream->xfer_result = result; + } } + cf_quiche_flush_body(cf, data, stream); } -#else -#define cf_ev_name(x) "" -#endif -static CURLcode h3_process_event(struct Curl_cfilter *cf, +static void cf_quiche_process_ev(struct Curl_cfilter *cf, struct Curl_easy *data, struct h3_stream_ctx *stream, quiche_h3_event *ev) { - struct cb_ctx cb_ctx; - CURLcode result = CURLE_OK; - int rc; - if(!stream) - return CURLE_OK; + return; + switch(quiche_h3_event_type(ev)) { - case QUICHE_H3_EVENT_HEADERS: + case QUICHE_H3_EVENT_HEADERS: { + struct cb_ctx cb_ctx; stream->resp_got_header = TRUE; cb_ctx.cf = cf; cb_ctx.data = data; - rc = quiche_h3_event_for_each_header(ev, cb_each_header, &cb_ctx); - if(rc) { - failf(data, "Error %d in HTTP/3 response header for stream[%" - FMT_PRIu64"]", rc, stream->id); - return CURLE_RECV_ERROR; - } - CURL_TRC_CF(data, cf, "[%"FMT_PRIu64"] <- [HEADERS]", stream->id); + cb_ctx.stream = stream; + quiche_h3_event_for_each_header(ev, cb_each_header, &cb_ctx); + CURL_TRC_CF(data, cf, "[%" PRIu64 "] <- [HEADERS]", stream->id); + Curl_multi_mark_dirty(data); break; - + } case QUICHE_H3_EVENT_DATA: - if(!stream->closed) { - result = cf_recv_body(cf, data); + if(!stream->resp_hds_complete) { + stream->resp_hds_complete = TRUE; + cf_quiche_write_hd(cf, data, stream, "\r\n", 2, FALSE); } + cf_quiche_recv_body(cf, data, stream); + CURL_TRC_CF(data, cf, "[%" PRIu64 "] <- [DATA]", stream->id); + Curl_multi_mark_dirty(data); break; case QUICHE_H3_EVENT_RESET: - CURL_TRC_CF(data, cf, "[%"FMT_PRIu64"] RESET", stream->id); + CURL_TRC_CF(data, cf, "[%" PRIu64 "] RESET", stream->id); stream->closed = TRUE; stream->reset = TRUE; stream->send_closed = TRUE; - streamclose(cf->conn, "Reset of stream"); + Curl_multi_mark_dirty(data); break; case QUICHE_H3_EVENT_FINISHED: - CURL_TRC_CF(data, cf, "[%"FMT_PRIu64"] CLOSED", stream->id); + CURL_TRC_CF(data, cf, "[%" PRIu64 "] CLOSED", stream->id); if(!stream->resp_hds_complete) { - result = write_resp_raw(cf, data, "\r\n", 2); - if(result) - return result; stream->resp_hds_complete = TRUE; + cf_quiche_write_hd(cf, data, stream, "\r\n", 2, TRUE); } stream->closed = TRUE; - streamclose(cf->conn, "End of stream"); + Curl_multi_mark_dirty(data); break; case QUICHE_H3_EVENT_GOAWAY: - CURL_TRC_CF(data, cf, "[%"FMT_PRIu64"] <- [GOAWAY]", stream->id); + CURL_TRC_CF(data, cf, "[%" PRIu64 "] <- [GOAWAY]", stream->id); break; default: - CURL_TRC_CF(data, cf, "[%"FMT_PRIu64"] recv, unhandled event %d", + CURL_TRC_CF(data, cf, "[%" PRIu64 "] recv, unhandled event %d", stream->id, quiche_h3_event_type(ev)); break; } - return result; -} - -static CURLcode cf_quiche_ev_process(struct Curl_cfilter *cf, - struct Curl_easy *data, - struct h3_stream_ctx *stream, - quiche_h3_event *ev) -{ - CURLcode result = h3_process_event(cf, data, stream, ev); - Curl_multi_mark_dirty(data); - if(result) - CURL_TRC_CF(data, cf, "error processing event %s " - "for [%"FMT_PRIu64"] -> %d", cf_ev_name(ev), - stream->id, result); - return result; } struct cf_quich_disp_ctx { - curl_uint64_t stream_id; + uint64_t stream_id; struct Curl_cfilter *cf; struct Curl_multi *multi; quiche_h3_event *ev; - CURLcode result; }; -static bool cf_quiche_disp_event(unsigned int mid, void *val, void *user_data) +static bool cf_quiche_disp_event(uint32_t mid, void *val, void *user_data) { struct cf_quich_disp_ctx *dctx = user_data; struct h3_stream_ctx *stream = val; @@ -570,7 +570,7 @@ static bool cf_quiche_disp_event(unsigned int mid, void *val, void *user_data) if(stream->id == dctx->stream_id) { struct Curl_easy *sdata = Curl_multi_get_easy(dctx->multi, mid); if(sdata) - dctx->result = cf_quiche_ev_process(dctx->cf, sdata, stream, dctx->ev); + cf_quiche_process_ev(dctx->cf, sdata, stream, dctx->ev); return FALSE; /* stop iterating */ } return TRUE; @@ -585,33 +585,32 @@ static CURLcode cf_poll_events(struct Curl_cfilter *cf, /* Take in the events and distribute them to the transfers. */ while(ctx->h3c) { - curl_int64_t stream3_id = quiche_h3_conn_poll(ctx->h3c, ctx->qconn, &ev); - if(stream3_id == QUICHE_H3_ERR_DONE) { + int64_t rv = quiche_h3_conn_poll(ctx->h3c, ctx->qconn, &ev); + if(rv == QUICHE_H3_ERR_DONE) { break; } - else if(stream3_id < 0) { - CURL_TRC_CF(data, cf, "error poll: %"FMT_PRId64, stream3_id); + else if(rv < 0) { + CURL_TRC_CF(data, cf, "error poll: %" PRId64, rv); return CURLE_HTTP3; } else { - struct cf_quich_disp_ctx dctx; - dctx.stream_id = (curl_uint64_t)stream3_id; - dctx.cf = cf; - dctx.multi = data->multi; - dctx.ev = ev; - dctx.result = CURLE_OK; stream = H3_STREAM_CTX(ctx, data); - if(stream && stream->id == dctx.stream_id) { + if(stream && stream->id == (uint64_t)rv) { /* event for calling transfer */ - CURLcode result = cf_quiche_ev_process(cf, data, stream, ev); + cf_quiche_process_ev(cf, data, stream, ev); quiche_h3_event_free(ev); - if(result) - return result; + if(stream->xfer_result) + return stream->xfer_result; } else { /* another transfer, do not return errors, as they are not for * the calling transfer */ - Curl_uint_hash_visit(&ctx->streams, cf_quiche_disp_event, &dctx); + struct cf_quich_disp_ctx dctx; + dctx.stream_id = (uint64_t)rv; + dctx.cf = cf; + dctx.multi = data->multi; + dctx.ev = ev; + Curl_uint32_hash_visit(&ctx->streams, cf_quiche_disp_event, &dctx); quiche_h3_event_free(ev); } } @@ -625,58 +624,63 @@ struct recv_ctx { int pkts; }; -static CURLcode recv_pkt(const unsigned char *pkt, size_t pktlen, - struct sockaddr_storage *remote_addr, - socklen_t remote_addrlen, int ecn, - void *userp) +static CURLcode cf_quiche_recv_pkts(const unsigned char *buf, size_t buflen, + size_t gso_size, + struct sockaddr_storage *remote_addr, + socklen_t remote_addrlen, int ecn, + void *userp) { struct recv_ctx *r = userp; struct cf_quiche_ctx *ctx = r->cf->ctx; quiche_recv_info recv_info; - ssize_t nread; + size_t pktlen, offset, nread; + ssize_t rv; (void)ecn; - ++r->pkts; recv_info.to = (struct sockaddr *)&ctx->q.local_addr; recv_info.to_len = ctx->q.local_addrlen; recv_info.from = (struct sockaddr *)remote_addr; recv_info.from_len = remote_addrlen; - nread = quiche_conn_recv(ctx->qconn, - (unsigned char *)CURL_UNCONST(pkt), pktlen, - &recv_info); - if(nread < 0) { - if(QUICHE_ERR_DONE == nread) { - if(quiche_conn_is_draining(ctx->qconn)) { - CURL_TRC_CF(r->data, r->cf, "ingress, connection is draining"); - return CURLE_RECV_ERROR; + for(offset = 0; offset < buflen; offset += gso_size) { + pktlen = ((offset + gso_size) <= buflen) ? gso_size : (buflen - offset); + rv = quiche_conn_recv(ctx->qconn, + (unsigned char *)CURL_UNCONST(buf + offset), + pktlen, &recv_info); + if(!curlx_sztouz(rv, &nread)) { + if(QUICHE_ERR_DONE == rv) { + if(quiche_conn_is_draining(ctx->qconn)) { + CURL_TRC_CF(r->data, r->cf, "ingress, connection is draining"); + return CURLE_RECV_ERROR; + } + if(quiche_conn_is_closed(ctx->qconn)) { + CURL_TRC_CF(r->data, r->cf, "ingress, connection is closed"); + return CURLE_RECV_ERROR; + } + CURL_TRC_CF(r->data, r->cf, "ingress, quiche is DONE"); + return CURLE_OK; } - if(quiche_conn_is_closed(ctx->qconn)) { - CURL_TRC_CF(r->data, r->cf, "ingress, connection is closed"); + else if(QUICHE_ERR_TLS_FAIL == rv) { + long verify_ok = SSL_get_verify_result(ctx->tls.ossl.ssl); + if(verify_ok != X509_V_OK) { + failf(r->data, "SSL certificate problem: %s", + X509_verify_cert_error_string(verify_ok)); + return CURLE_PEER_FAILED_VERIFICATION; + } + failf(r->data, "ingress, quiche reports TLS fail"); return CURLE_RECV_ERROR; } - CURL_TRC_CF(r->data, r->cf, "ingress, quiche is DONE"); - return CURLE_OK; - } - else if(QUICHE_ERR_TLS_FAIL == nread) { - long verify_ok = SSL_get_verify_result(ctx->tls.ossl.ssl); - if(verify_ok != X509_V_OK) { - failf(r->data, "SSL certificate problem: %s", - X509_verify_cert_error_string(verify_ok)); - return CURLE_PEER_FAILED_VERIFICATION; + else { + failf(r->data, "quiche reports error %zd on receive", rv); + return CURLE_RECV_ERROR; } - failf(r->data, "ingress, quiche reports TLS fail"); - return CURLE_RECV_ERROR; } - else { - failf(r->data, "quiche reports error %zd on receive", nread); - return CURLE_RECV_ERROR; + else if(nread < pktlen) { + CURL_TRC_CF(r->data, r->cf, "ingress, quiche only read %zu/%zu bytes", + nread, pktlen); } - } - else if((size_t)nread < pktlen) { - CURL_TRC_CF(r->data, r->cf, "ingress, quiche only read %zd/%zu bytes", - nread, pktlen); + ++r->pkts; } return CURLE_OK; @@ -698,7 +702,8 @@ static CURLcode cf_process_ingress(struct Curl_cfilter *cf, rctx.data = data; rctx.pkts = 0; - result = vquic_recv_packets(cf, data, &ctx->q, 1000, recv_pkt, &rctx); + result = vquic_recv_packets(cf, data, &ctx->q, 1000, + cf_quiche_recv_pkts, &rctx); if(result) return result; @@ -723,18 +728,17 @@ static CURLcode read_pkt_to_send(void *userp, { struct read_ctx *x = userp; struct cf_quiche_ctx *ctx = x->cf->ctx; - ssize_t n; + ssize_t rv; *pnread = 0; - n = quiche_conn_send(ctx->qconn, buf, buflen, &x->send_info); - if(n == QUICHE_ERR_DONE) + rv = quiche_conn_send(ctx->qconn, buf, buflen, &x->send_info); + if(rv == QUICHE_ERR_DONE) return CURLE_AGAIN; - if(n < 0) { - failf(x->data, "quiche_conn_send returned %zd", n); + if(!curlx_sztouz(rv, pnread)) { + failf(x->data, "quiche_conn_send returned %zd", rv); return CURLE_SEND_ERROR; } - *pnread = (size_t)n; return CURLE_OK; } @@ -748,8 +752,8 @@ static CURLcode cf_flush_egress(struct Curl_cfilter *cf, struct cf_quiche_ctx *ctx = cf->ctx; size_t nread; CURLcode result; - curl_int64_t expiry_ns; - curl_int64_t timeout_ns; + int64_t expiry_ns; + int64_t timeout_ns; struct read_ctx readx; size_t pkt_count, gsolen; @@ -819,7 +823,7 @@ static CURLcode cf_flush_egress(struct Curl_cfilter *cf, timeout_ns = quiche_conn_timeout_as_nanos(ctx->qconn); if(timeout_ns % 1000000) timeout_ns += 1000000; - /* expire resolution is milliseconds */ + /* expire resolution is milliseconds */ Curl_expire(data, (timeout_ns / 1000000), EXPIRE_QUIC); return result; } @@ -835,15 +839,13 @@ static CURLcode recv_closed_stream(struct Curl_cfilter *cf, DEBUGASSERT(stream); *pnread = 0; if(stream->reset) { - failf(data, - "HTTP/3 stream %" FMT_PRIu64 " reset by server", stream->id); + failf(data, "HTTP/3 stream %" PRIu64 " reset by server", stream->id); result = data->req.bytecount ? CURLE_PARTIAL_FILE : CURLE_HTTP3; - CURL_TRC_CF(data, cf, "[%" FMT_PRIu64 "] cf_recv, was reset -> %d", + CURL_TRC_CF(data, cf, "[%" PRIu64 "] cf_recv, was reset -> %d", stream->id, result); } else if(!stream->resp_got_header) { - failf(data, - "HTTP/3 stream %" FMT_PRIu64 " was closed cleanly, but before " + failf(data, "HTTP/3 stream %" PRIu64 " was closed cleanly, but before " "getting all response header fields, treated as error", stream->id); result = CURLE_HTTP3; @@ -852,128 +854,107 @@ static CURLcode recv_closed_stream(struct Curl_cfilter *cf, } static CURLcode cf_quiche_recv(struct Curl_cfilter *cf, struct Curl_easy *data, - char *buf, size_t len, size_t *pnread) + char *buf, size_t blen, size_t *pnread) { struct cf_quiche_ctx *ctx = cf->ctx; struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); CURLcode result = CURLE_OK; *pnread = 0; - vquic_ctx_update_time(&ctx->q); + (void)buf; + (void)blen; + vquic_ctx_update_time(&ctx->q, Curl_pgrs_now(data)); if(!stream) return CURLE_RECV_ERROR; - - if(!Curl_bufq_is_empty(&stream->recvbuf)) { - result = Curl_bufq_cread(&stream->recvbuf, buf, len, pnread); - CURL_TRC_CF(data, cf, "[%" FMT_PRIu64 "] read recvbuf(len=%zu) " - "-> %d, %zu", stream->id, len, result, *pnread); - if(result) - goto out; - } - result = cf_process_ingress(cf, data); if(result) { CURL_TRC_CF(data, cf, "cf_recv, error on ingress"); goto out; } - /* recvbuf had nothing before, maybe after progressing ingress? */ - if(!*pnread && !Curl_bufq_is_empty(&stream->recvbuf)) { - result = Curl_bufq_cread(&stream->recvbuf, buf, len, pnread); - CURL_TRC_CF(data, cf, "[%" FMT_PRIu64 "] read recvbuf(len=%zu) " - "-> %d, %zu", stream->id, len, result, *pnread); - if(result) - goto out; - } - - if(*pnread) { - if(stream->closed) - Curl_multi_mark_dirty(data); + if(stream->xfer_result) { + cf_quiche_stream_close(cf, data, stream); + result = stream->xfer_result; + goto out; } - else { - if(stream->closed) - result = recv_closed_stream(cf, data, pnread); - else if(quiche_conn_is_draining(ctx->qconn)) { - failf(data, "QUIC connection is draining"); - result = CURLE_HTTP3; - } - else - result = CURLE_AGAIN; + else if(stream->closed) + result = recv_closed_stream(cf, data, pnread); + else if(quiche_conn_is_draining(ctx->qconn)) { + failf(data, "QUIC connection is draining"); + result = CURLE_HTTP3; } + else + result = CURLE_AGAIN; out: result = Curl_1st_err(result, cf_flush_egress(cf, data)); if(*pnread > 0) ctx->data_recvd += *pnread; - CURL_TRC_CF(data, cf, "[%"FMT_PRIu64"] cf_recv(total=%" - FMT_OFF_T ") -> %d, %zu", - stream->id, ctx->data_recvd, result, *pnread); + CURL_TRC_CF(data, cf, "[%" PRIu64 "] cf_recv(len=%zu) -> %d, %zu, total=%" + FMT_OFF_T, stream->id, blen, result, *pnread, ctx->data_recvd); return result; } static CURLcode cf_quiche_send_body(struct Curl_cfilter *cf, struct Curl_easy *data, struct h3_stream_ctx *stream, - const void *buf, size_t len, bool eos, + const uint8_t *buf, size_t len, bool eos, size_t *pnwritten) { struct cf_quiche_ctx *ctx = cf->ctx; - ssize_t nwritten; + ssize_t rv; *pnwritten = 0; - nwritten = quiche_h3_send_body(ctx->h3c, ctx->qconn, stream->id, - (uint8_t *)CURL_UNCONST(buf), len, eos); - if(nwritten == QUICHE_H3_ERR_DONE || (nwritten == 0 && len > 0)) { + rv = quiche_h3_send_body(ctx->h3c, ctx->qconn, stream->id, + (uint8_t *)CURL_UNCONST(buf), len, eos); + if(rv == QUICHE_H3_ERR_DONE || (rv == 0 && len > 0)) { /* Blocked on flow control and should HOLD sending. But when do we open * again? */ if(!quiche_conn_stream_writable(ctx->qconn, stream->id, len)) { - CURL_TRC_CF(data, cf, "[%" FMT_PRIu64 "] send_body(len=%zu) " + CURL_TRC_CF(data, cf, "[%" PRIu64 "] send_body(len=%zu) " "-> window exhausted", stream->id, len); stream->quic_flow_blocked = TRUE; } return CURLE_AGAIN; } - else if(nwritten == QUICHE_H3_TRANSPORT_ERR_INVALID_STREAM_STATE) { - CURL_TRC_CF(data, cf, "[%" FMT_PRIu64 "] send_body(len=%zu) " + else if(rv == QUICHE_H3_TRANSPORT_ERR_INVALID_STREAM_STATE) { + CURL_TRC_CF(data, cf, "[%" PRIu64 "] send_body(len=%zu) " "-> invalid stream state", stream->id, len); return CURLE_HTTP3; } - else if(nwritten == QUICHE_H3_TRANSPORT_ERR_FINAL_SIZE) { - CURL_TRC_CF(data, cf, "[%" FMT_PRIu64 "] send_body(len=%zu) " - "-> exceeds size", stream->id, len); + else if(rv == QUICHE_H3_TRANSPORT_ERR_FINAL_SIZE) { + CURL_TRC_CF(data, cf, "[%" PRIu64 "] send_body(len=%zu) -> exceeds size", + stream->id, len); return CURLE_SEND_ERROR; } - else if(nwritten < 0) { - CURL_TRC_CF(data, cf, "[%" FMT_PRIu64 "] send_body(len=%zu) " - "-> quiche err %zd", stream->id, len, nwritten); + else if(!curlx_sztouz(rv, pnwritten)) { + CURL_TRC_CF(data, cf, "[%" PRIu64 "] send_body(len=%zu) -> quiche err %zd", + stream->id, len, rv); return CURLE_SEND_ERROR; } else { - if(eos && (len == (size_t)nwritten)) + if(eos && (len == *pnwritten)) stream->send_closed = TRUE; - CURL_TRC_CF(data, cf, "[%" FMT_PRIu64 "] send body(len=%zu, " - "eos=%d) -> %zd", - stream->id, len, stream->send_closed, nwritten); - *pnwritten = (size_t)nwritten; + CURL_TRC_CF(data, cf, "[%" PRIu64 "] send body(len=%zu, eos=%d) -> %zu", + stream->id, len, stream->send_closed, *pnwritten); return CURLE_OK; } } static CURLcode h3_open_stream(struct Curl_cfilter *cf, struct Curl_easy *data, - const char *buf, size_t blen, bool eos, + const uint8_t *buf, size_t blen, bool eos, size_t *pnwritten) { struct cf_quiche_ctx *ctx = cf->ctx; struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); size_t nheader, i; - curl_int64_t stream3_id; + int64_t rv; struct dynhds h2_headers; quiche_h3_header *nva = NULL; CURLcode result = CURLE_OK; - ssize_t nwritten; *pnwritten = 0; if(!stream) { @@ -987,8 +968,12 @@ static CURLcode h3_open_stream(struct Curl_cfilter *cf, Curl_dynhds_init(&h2_headers, 0, DYN_HTTP_REQUEST); DEBUGASSERT(stream); - nwritten = Curl_h1_req_parse_read(&stream->h1, buf, blen, NULL, 0, &result); - if(nwritten < 0) + + result = Curl_h1_req_parse_read(&stream->h1, buf, blen, NULL, + !data->state.http_ignorecustom ? + data->set.str[STRING_CUSTOMREQUEST] : NULL, + 0, pnwritten); + if(result) goto out; if(!stream->h1.done) { /* need more data */ @@ -1004,7 +989,7 @@ static CURLcode h3_open_stream(struct Curl_cfilter *cf, Curl_h1_req_parse_free(&stream->h1); nheader = Curl_dynhds_count(&h2_headers); - nva = malloc(sizeof(quiche_h3_header) * nheader); + nva = curlx_malloc(sizeof(quiche_h3_header) * nheader); if(!nva) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -1018,70 +1003,69 @@ static CURLcode h3_open_stream(struct Curl_cfilter *cf, nva[i].value_len = e->valuelen; } - *pnwritten = (size_t)nwritten; buf += *pnwritten; blen -= *pnwritten; if(eos && !blen) stream->send_closed = TRUE; - stream3_id = quiche_h3_send_request(ctx->h3c, ctx->qconn, nva, nheader, - stream->send_closed); - CURL_TRC_CF(data, cf, "quiche_send_request() -> %" FMT_PRIu64, stream3_id); - if(stream3_id < 0) { - if(QUICHE_H3_ERR_STREAM_BLOCKED == stream3_id) { + rv = quiche_h3_send_request(ctx->h3c, ctx->qconn, nva, nheader, + stream->send_closed); + CURL_TRC_CF(data, cf, "quiche_send_request() -> %" PRId64, rv); + if(rv < 0) { + if(QUICHE_H3_ERR_STREAM_BLOCKED == rv) { /* quiche seems to report this error if the connection window is * exhausted. Which happens frequently and intermittent. */ - CURL_TRC_CF(data, cf, "[%"FMT_PRIu64"] blocked", stream->id); + CURL_TRC_CF(data, cf, "[%" PRIu64 "] blocked", stream->id); stream->quic_flow_blocked = TRUE; result = CURLE_AGAIN; goto out; } else { - CURL_TRC_CF(data, cf, "send_request(%s) -> %" FMT_PRIu64, - data->state.url, stream3_id); + CURL_TRC_CF(data, cf, "send_request(%s) -> %" PRIu64, + Curl_bufref_ptr(&data->state.url), rv); } result = CURLE_SEND_ERROR; goto out; } DEBUGASSERT(!stream->opened); - stream->id = stream3_id; + stream->id = (uint64_t)rv; stream->opened = TRUE; stream->closed = FALSE; stream->reset = FALSE; if(Curl_trc_is_verbose(data)) { - infof(data, "[HTTP/3] [%" FMT_PRIu64 "] OPENED stream for %s", - stream->id, data->state.url); + infof(data, "[HTTP/3] [%" PRIu64 "] OPENED stream for %s", + stream->id, Curl_bufref_ptr(&data->state.url)); for(i = 0; i < nheader; ++i) { - infof(data, "[HTTP/3] [%" FMT_PRIu64 "] [%.*s: %.*s]", stream->id, + infof(data, "[HTTP/3] [%" PRIu64 "] [%.*s: %.*s]", stream->id, (int)nva[i].name_len, nva[i].name, (int)nva[i].value_len, nva[i].value); } } if(blen) { /* after the headers, there was request BODY data */ - size_t bwritten; + size_t nwritten; CURLcode r2 = CURLE_OK; - r2 = cf_quiche_send_body(cf, data, stream, buf, blen, eos, &bwritten); + r2 = cf_quiche_send_body(cf, data, stream, buf, blen, eos, &nwritten); if(r2 && (CURLE_AGAIN != r2)) { /* real error, fail */ result = r2; } - else if(bwritten > 0) { - *pnwritten += (size_t)bwritten; + else if(nwritten > 0) { + *pnwritten += nwritten; } } out: - free(nva); + curlx_free(nva); Curl_dynhds_free(&h2_headers); return result; } static CURLcode cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, bool eos, + const uint8_t *buf, size_t len, bool eos, size_t *pnwritten) { struct cf_quiche_ctx *ctx = cf->ctx; @@ -1089,7 +1073,7 @@ static CURLcode cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data, CURLcode result; *pnwritten = 0; - vquic_ctx_update_time(&ctx->q); + vquic_ctx_update_time(&ctx->q, Curl_pgrs_now(data)); result = cf_process_ingress(cf, data); if(result) @@ -1101,6 +1085,10 @@ static CURLcode cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data, goto out; stream = H3_STREAM_CTX(ctx, data); } + else if(stream->xfer_result) { + cf_quiche_stream_close(cf, data, stream); + result = stream->xfer_result; + } else if(stream->closed) { if(stream->resp_hds_complete) { /* sending request body on a stream that has been closed by the @@ -1111,13 +1099,13 @@ static CURLcode cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data, * 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, "[%" FMT_PRIu64 "] discarding data" + CURL_TRC_CF(data, cf, "[%" PRIu64 "] discarding data" "on closed stream with response", stream->id); result = CURLE_OK; *pnwritten = len; goto out; } - CURL_TRC_CF(data, cf, "[%" FMT_PRIu64 "] send_body(len=%zu) " + CURL_TRC_CF(data, cf, "[%" PRIu64 "] send_body(len=%zu) " "-> stream closed", stream->id, len); result = CURLE_HTTP3; goto out; @@ -1129,8 +1117,8 @@ static CURLcode cf_quiche_send(struct Curl_cfilter *cf, struct Curl_easy *data, out: result = Curl_1st_err(result, cf_flush_egress(cf, data)); - CURL_TRC_CF(data, cf, "[%" FMT_PRIu64 "] cf_send(len=%zu) -> %d, %zu", - stream ? stream->id : (curl_uint64_t)~0, len, + CURL_TRC_CF(data, cf, "[%" PRIu64 "] cf_send(len=%zu) -> %d, %zu", + stream ? stream->id : (uint64_t)~0, len, result, *pnwritten); return result; } @@ -1142,7 +1130,7 @@ static bool stream_is_writeable(struct Curl_cfilter *cf, struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); return stream && (quiche_conn_stream_writable( - ctx->qconn, (curl_uint64_t)stream->id, 1) > 0); + ctx->qconn, stream->id, 1) > 0); } static CURLcode cf_quiche_adjust_pollset(struct Curl_cfilter *cf, @@ -1174,19 +1162,6 @@ static CURLcode cf_quiche_adjust_pollset(struct Curl_cfilter *cf, return result; } -/* - * Called from transfer.c:data_pending to know if we should keep looping - * to receive more data from the connection. - */ -static bool cf_quiche_data_pending(struct Curl_cfilter *cf, - const struct Curl_easy *data) -{ - struct cf_quiche_ctx *ctx = cf->ctx; - const struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data); - (void)cf; - return stream && !Curl_bufq_is_empty(&stream->recvbuf); -} - static CURLcode h3_data_pause(struct Curl_cfilter *cf, struct Curl_easy *data, bool pause) @@ -1227,7 +1202,7 @@ static CURLcode cf_quiche_cntrl(struct Curl_cfilter *cf, stream->send_closed = TRUE; body[0] = 'X'; result = cf_quiche_send(cf, data, body, 0, TRUE, &sent); - CURL_TRC_CF(data, cf, "[%"FMT_PRIu64"] DONE_SEND -> %d, %zu", + CURL_TRC_CF(data, cf, "[%" PRIu64 "] DONE_SEND -> %d, %zu", stream->id, result, sent); } break; @@ -1251,12 +1226,12 @@ static CURLcode cf_quiche_ctx_open(struct Curl_cfilter *cf, int rv; CURLcode result; const struct Curl_sockaddr_ex *sockaddr; - static const struct alpn_spec ALPN_SPEC_H3 = {{ "h3" }, 1}; + static const struct alpn_spec ALPN_SPEC_H3 = { { "h3" }, 1 }; DEBUGASSERT(ctx->q.sockfd != CURL_SOCKET_BAD); DEBUGASSERT(ctx->initialized); - result = vquic_ctx_init(&ctx->q); + result = vquic_ctx_init(data, &ctx->q); if(result) return result; @@ -1322,8 +1297,7 @@ static CURLcode cf_quiche_ctx_open(struct Curl_cfilter *cf, int qfd; (void)Curl_qlogdir(data, ctx->scid, sizeof(ctx->scid), &qfd); if(qfd != -1) - quiche_conn_set_qlog_fd(ctx->qconn, qfd, - "qlog title", "curl qlog"); + quiche_conn_set_qlog_fd(ctx->qconn, qfd, "qlog title", "curl qlog"); } #endif @@ -1376,7 +1350,7 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf, } *done = FALSE; - vquic_ctx_update_time(&ctx->q); + vquic_ctx_update_time(&ctx->q, Curl_pgrs_now(data)); if(!ctx->qconn) { result = cf_quiche_ctx_open(cf, data); @@ -1398,8 +1372,8 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf, if(quiche_conn_is_established(ctx->qconn)) { ctx->handshake_at = ctx->q.last_op; - CURL_TRC_CF(data, cf, "handshake complete after %dms", - (int)curlx_timediff(ctx->handshake_at, ctx->started_at)); + CURL_TRC_CF(data, cf, "handshake complete after %" FMT_TIMEDIFF_T "ms", + curlx_ptimediff_ms(&ctx->handshake_at, &ctx->started_at)); result = cf_quiche_verify_peer(cf, data); if(!result) { CURL_TRC_CF(data, cf, "peer verified"); @@ -1417,7 +1391,6 @@ static CURLcode cf_quiche_connect(struct Curl_cfilter *cf, } cf->connected = TRUE; *done = TRUE; - connkeep(cf->conn, "HTTP/3 default"); } } else if(quiche_conn_is_draining(ctx->qconn)) { @@ -1459,7 +1432,7 @@ static CURLcode cf_quiche_shutdown(struct Curl_cfilter *cf, int err; ctx->shutdown_started = TRUE; - vquic_ctx_update_time(&ctx->q); + vquic_ctx_update_time(&ctx->q, Curl_pgrs_now(data)); err = quiche_conn_close(ctx->qconn, TRUE, 0, NULL, 0); if(err) { CURL_TRC_CF(data, cf, "error %d adding shutdown packet, " @@ -1518,19 +1491,20 @@ static CURLcode cf_quiche_query(struct Curl_cfilter *cf, switch(query) { case CF_QUERY_MAX_CONCURRENT: { - curl_uint64_t max_streams = CONN_ATTACHED(cf->conn); + uint64_t max_streams = cf->conn->attached_xfers; if(!ctx->goaway && ctx->qconn) { max_streams += quiche_conn_peer_streams_left_bidi(ctx->qconn); } *pres1 = (max_streams > INT_MAX) ? INT_MAX : (int)max_streams; CURL_TRC_CF(data, cf, "query conn[%" FMT_OFF_T "]: " "MAX_CONCURRENT -> %d (%u in use)", - cf->conn->connection_id, *pres1, CONN_ATTACHED(cf->conn)); + cf->conn->connection_id, *pres1, cf->conn->attached_xfers); return CURLE_OK; } case CF_QUERY_CONNECT_REPLY_MS: if(ctx->q.got_first_byte) { - timediff_t ms = curlx_timediff(ctx->q.first_byte_at, ctx->started_at); + timediff_t ms = curlx_ptimediff_ms(&ctx->q.first_byte_at, + &ctx->started_at); *pres1 = (ms < INT_MAX) ? (int)ms : INT_MAX; } else @@ -1619,7 +1593,7 @@ struct Curl_cftype Curl_cft_http3 = { cf_quiche_close, cf_quiche_shutdown, cf_quiche_adjust_pollset, - cf_quiche_data_pending, + Curl_cf_def_data_pending, cf_quiche_send, cf_quiche_recv, cf_quiche_cntrl, @@ -1639,7 +1613,7 @@ CURLcode Curl_cf_quiche_create(struct Curl_cfilter **pcf, (void)data; (void)conn; - ctx = calloc(1, sizeof(*ctx)); + ctx = curlx_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 index fa89c0b80967..204a72224996 100644 --- a/lib/vquic/vquic-tls.c +++ b/lib/vquic/vquic-tls.c @@ -45,18 +45,12 @@ #endif #include "../urldata.h" -#include "../curl_trc.h" #include "../cfilters.h" -#include "../multiif.h" #include "../vtls/keylog.h" #include "../vtls/vtls.h" #include "../vtls/vtls_scache.h" #include "vquic-tls.h" -/* The last 2 #include files should be in this order */ -#include "../curl_memory.h" -#include "../memdebug.h" - CURLcode Curl_vquic_tls_init(struct curl_tls_ctx *ctx, struct Curl_cfilter *cf, struct Curl_easy *data, @@ -147,7 +141,9 @@ CURLcode Curl_vquic_tls_before_recv(struct curl_tls_ctx *ctx, return result; } #else - (void)ctx; (void)cf; (void)data; + (void)ctx; + (void)cf; + (void)data; #endif return CURLE_OK; } @@ -168,22 +164,25 @@ CURLcode Curl_vquic_tls_verify_peer(struct curl_tls_ctx *ctx, (void)conn_config; result = Curl_ossl_check_peer_cert(cf, data, &ctx->ossl, peer); #elif defined(USE_GNUTLS) - if(conn_config->verifyhost) { - result = Curl_gtls_verifyserver(cf, data, ctx->gtls.session, - conn_config, &data->set.ssl, peer, - data->set.str[STRING_SSL_PINNEDPUBLICKEY]); - if(result) - return result; - } + result = Curl_gtls_verifyserver(cf, data, ctx->gtls.session, + conn_config, &data->set.ssl, peer, + data->set.str[STRING_SSL_PINNEDPUBLICKEY]); + if(result) + return result; #elif defined(USE_WOLFSSL) (void)data; if(conn_config->verifyhost) { - char *snihost = peer->sni ? peer->sni : peer->hostname; - WOLFSSL_X509* cert = wolfSSL_get_peer_certificate(ctx->wssl.ssl); - if(wolfSSL_X509_check_host(cert, snihost, strlen(snihost), 0, NULL) - == WOLFSSL_FAILURE) { + WOLFSSL_X509 *cert = wolfSSL_get_peer_certificate(ctx->wssl.ssl); + if(!cert) + result = CURLE_OUT_OF_MEMORY; + else if(peer->sni && + (wolfSSL_X509_check_host(cert, peer->sni, strlen(peer->sni), 0, + NULL) == WOLFSSL_FAILURE)) + result = CURLE_PEER_FAILED_VERIFICATION; + else if(!peer->sni && + (wolfSSL_X509_check_ip_asc(cert, peer->hostname, + 0) == WOLFSSL_FAILURE)) result = CURLE_PEER_FAILED_VERIFICATION; - } wolfSSL_X509_free(cert); } if(!result) @@ -195,7 +194,6 @@ CURLcode Curl_vquic_tls_verify_peer(struct curl_tls_ctx *ctx, return result; } - bool Curl_vquic_tls_get_ssl_info(struct curl_tls_ctx *ctx, bool give_ssl_ctx, struct curl_tlssessioninfo *info) diff --git a/lib/vquic/vquic-tls.h b/lib/vquic/vquic-tls.h index c694e23e4e6d..a14714532d03 100644 --- a/lib/vquic/vquic-tls.h +++ b/lib/vquic/vquic-tls.h @@ -25,14 +25,15 @@ ***************************************************************************/ #include "../curl_setup.h" -#include "../bufq.h" -#include "../vtls/vtls.h" -#include "../vtls/vtls_int.h" -#include "../vtls/openssl.h" #if defined(USE_HTTP3) && \ (defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_WOLFSSL)) +#include "../bufq.h" +#include "../vtls/vtls.h" +#include "../vtls/vtls_int.h" + +#include "../vtls/openssl.h" #include "../vtls/wolfssl.h" struct ssl_peer; @@ -69,14 +70,14 @@ typedef CURLcode Curl_vquic_session_reuse_cb(struct Curl_cfilter *cf, /** * 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 alpns the ALPN specifications to negotiate, may be NULL - * @param cb_setup optional callback for early TLS config - * @param cb_user_data user_data param for callback - * @param ssl_user_data optional pointer to set in TLS application context + * @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 alpns the ALPN specifications to negotiate, may be NULL + * @param cb_setup optional callback for early TLS config + * @param cb_user_data user_data param for callback + * @param ssl_user_data optional pointer to set in TLS application context * @param session_reuse_cb callback to handle session reuse, signal early data */ CURLcode Curl_vquic_tls_init(struct curl_tls_ctx *ctx, diff --git a/lib/vquic/vquic.c b/lib/vquic/vquic.c index 30917b835af0..5869e70bbc69 100644 --- a/lib/vquic/vquic.c +++ b/lib/vquic/vquic.c @@ -40,23 +40,19 @@ #include "curl_osslq.h" #include "curl_quiche.h" #include "../multiif.h" +#include "../progress.h" #include "../rand.h" #include "vquic.h" #include "vquic_int.h" #include "../curlx/strerr.h" #include "../curlx/strparse.h" -/* The last 2 #include files should be in this order */ -#include "../curl_memory.h" -#include "../memdebug.h" - #if !defined(CURL_DISABLE_HTTP) && defined(USE_HTTP3) #define NW_CHUNK_SIZE (64 * 1024) #define NW_SEND_CHUNKS 1 - int Curl_vquic_init(void) { #if defined(USE_NGTCP2) && defined(OPENSSL_QUIC_API2) @@ -78,7 +74,8 @@ void Curl_quic_ver(char *p, size_t len) #endif } -CURLcode vquic_ctx_init(struct cf_quic_ctx *qctx) +CURLcode vquic_ctx_init(struct Curl_easy *data, + struct cf_quic_ctx *qctx) { Curl_bufq_init2(&qctx->sendbuf, NW_CHUNK_SIZE, NW_SEND_CHUNKS, BUFQ_OPT_SOFT_LIMIT); @@ -97,7 +94,7 @@ CURLcode vquic_ctx_init(struct cf_quic_ctx *qctx) } } #endif - vquic_ctx_update_time(qctx); + vquic_ctx_set_time(qctx, Curl_pgrs_now(data)); return CURLE_OK; } @@ -107,9 +104,16 @@ void vquic_ctx_free(struct cf_quic_ctx *qctx) Curl_bufq_free(&qctx->sendbuf); } -void vquic_ctx_update_time(struct cf_quic_ctx *qctx) +void vquic_ctx_set_time(struct cf_quic_ctx *qctx, + const struct curltime *pnow) { - qctx->last_op = curlx_now(); + qctx->last_op = *pnow; +} + +void vquic_ctx_update_time(struct cf_quic_ctx *qctx, + const struct curltime *pnow) +{ + qctx->last_op = *pnow; } static CURLcode send_packet_no_gso(struct Curl_cfilter *cf, @@ -127,8 +131,8 @@ static CURLcode do_sendmsg(struct Curl_cfilter *cf, CURLcode result = CURLE_OK; #ifdef HAVE_SENDMSG struct iovec msg_iov; - struct msghdr msg = {0}; - ssize_t sent; + struct msghdr msg = { 0 }; + ssize_t rv; #if defined(__linux__) && defined(UDP_SEGMENT) uint8_t msg_ctrl[32]; struct cmsghdr *cm; @@ -144,6 +148,7 @@ static CURLcode do_sendmsg(struct Curl_cfilter *cf, if(pktlen > gsolen) { /* Only set this, when we need it. macOS, for example, * does not seem to like a msg_control of length 0. */ + memset(msg_ctrl, 0, sizeof(msg_ctrl)); msg.msg_control = msg_ctrl; assert(sizeof(msg_ctrl) >= CMSG_SPACE(sizeof(int))); msg.msg_controllen = CMSG_SPACE(sizeof(int)); @@ -155,12 +160,10 @@ static CURLcode do_sendmsg(struct Curl_cfilter *cf, } #endif - - while((sent = sendmsg(qctx->sockfd, &msg, 0)) == -1 && - SOCKERRNO == SOCKEINTR) + while((rv = sendmsg(qctx->sockfd, &msg, 0)) == -1 && SOCKERRNO == SOCKEINTR) ; - if(sent == -1) { + if(!curlx_sztouz(rv, psent)) { switch(SOCKERRNO) { case EAGAIN: #if EAGAIN != SOCKEWOULDBLOCK @@ -173,41 +176,41 @@ static CURLcode do_sendmsg(struct Curl_cfilter *cf, case EIO: if(pktlen > gsolen) { /* GSO failure */ - infof(data, "sendmsg() returned %zd (errno %d); disable GSO", sent, + infof(data, "sendmsg() returned %zd (errno %d); disable GSO", rv, SOCKERRNO); qctx->no_gso = TRUE; return send_packet_no_gso(cf, data, qctx, pkt, pktlen, gsolen, psent); } FALLTHROUGH(); default: - failf(data, "sendmsg() returned %zd (errno %d)", sent, SOCKERRNO); + failf(data, "sendmsg() returned %zd (errno %d)", rv, SOCKERRNO); result = CURLE_SEND_ERROR; goto out; } } - else if(pktlen != (size_t)sent) { - failf(data, "sendmsg() sent only %zd/%zu bytes", sent, pktlen); + else if(pktlen != *psent) { + failf(data, "sendmsg() sent only %zu/%zu bytes", *psent, pktlen); result = CURLE_SEND_ERROR; goto out; } #else - ssize_t sent; + ssize_t rv; (void)gsolen; *psent = 0; - while((sent = CURL_SEND(qctx->sockfd, (const char *)pkt, - (SEND_TYPE_ARG3)pktlen, 0)) == -1 && + while((rv = CURL_SEND(qctx->sockfd, (const char *)pkt, + (SEND_TYPE_ARG3)pktlen, 0)) == -1 && SOCKERRNO == SOCKEINTR) ; - if(sent == -1) { + if(!curlx_sztouz(rv, psent)) { if(SOCKERRNO == EAGAIN || SOCKERRNO == SOCKEWOULDBLOCK) { result = CURLE_AGAIN; goto out; } else { - failf(data, "send() returned %zd (errno %d)", sent, SOCKERRNO); + failf(data, "send() returned %zd (errno %d)", rv, SOCKERRNO); if(SOCKERRNO != SOCKEMSGSIZE) { result = CURLE_SEND_ERROR; goto out; @@ -218,7 +221,6 @@ static CURLcode do_sendmsg(struct Curl_cfilter *cf, } #endif (void)cf; - *psent = pktlen; out: return result; @@ -270,7 +272,7 @@ static CURLcode vquic_send_packets(struct Curl_cfilter *cf, unsigned char c; *psent = 0; Curl_rand(data, &c, 1); - if(c >= ((100-qctx->wblock_percent)*256/100)) { + if(c >= ((100 - qctx->wblock_percent) * 256 / 100)) { CURL_TRC_CF(data, cf, "vquic_flush() simulate EWOULDBLOCK"); return CURLE_AGAIN; } @@ -338,8 +340,7 @@ CURLcode vquic_send_tail_split(struct Curl_cfilter *cf, struct Curl_easy *data, qctx->split_gsolen = gsolen; qctx->gsolen = tail_gsolen; CURL_TRC_CF(data, cf, "vquic_send_tail_split: [%zu gso=%zu][%zu gso=%zu]", - qctx->split_len, qctx->split_gsolen, - tail_len, qctx->gsolen); + qctx->split_len, qctx->split_gsolen, tail_len, qctx->gsolen); return vquic_flush(cf, data, qctx); } @@ -378,9 +379,16 @@ static CURLcode recvmmsg_packets(struct Curl_cfilter *cf, struct Curl_easy *data, struct cf_quic_ctx *qctx, size_t max_pkts, - vquic_recv_pkt_cb *recv_cb, void *userp) + vquic_recv_pkts_cb *recv_cb, void *userp) { +#if defined(__linux__) && defined(UDP_GRO) #define MMSG_NUM 16 +#define UDP_GRO_CNT_MAX 64 +#else +#define MMSG_NUM 64 +#define UDP_GRO_CNT_MAX 1 +#endif +#define MSG_BUF_SIZE (UDP_GRO_CNT_MAX * 1500) struct iovec msg_iov[MMSG_NUM]; struct mmsghdr mmsg[MMSG_NUM]; uint8_t msg_ctrl[MMSG_NUM * CMSG_SPACE(sizeof(int))]; @@ -390,17 +398,15 @@ static CURLcode recvmmsg_packets(struct Curl_cfilter *cf, char errstr[STRERROR_LEN]; CURLcode result = CURLE_OK; size_t gso_size; - size_t pktlen; - size_t offset, to; char *sockbuf = NULL; - uint8_t (*bufs)[64*1024] = NULL; + uint8_t (*bufs)[MSG_BUF_SIZE] = NULL; DEBUGASSERT(max_pkts > 0); - result = Curl_multi_xfer_sockbuf_borrow(data, MMSG_NUM * sizeof(bufs[0]), + result = Curl_multi_xfer_sockbuf_borrow(data, MMSG_NUM * MSG_BUF_SIZE, &sockbuf); if(result) goto out; - bufs = (uint8_t (*)[64*1024])sockbuf; + bufs = (uint8_t (*)[MSG_BUF_SIZE])sockbuf; total_nread = 0; while(pkts < max_pkts) { @@ -442,29 +448,21 @@ static CURLcode recvmmsg_packets(struct Curl_cfilter *cf, ++calls; for(i = 0; i < mcount; ++i) { + /* A zero-length UDP packet is no QUIC packet. Ignore. */ + if(!mmsg[i].msg_len) + continue; total_nread += mmsg[i].msg_len; gso_size = vquic_msghdr_get_udp_gro(&mmsg[i].msg_hdr); - if(gso_size == 0) { + if(gso_size == 0) gso_size = mmsg[i].msg_len; - } - for(offset = 0; offset < mmsg[i].msg_len; offset = to) { - ++pkts; - - to = offset + gso_size; - if(to > mmsg[i].msg_len) { - pktlen = mmsg[i].msg_len - offset; - } - else { - pktlen = gso_size; - } - - result = recv_cb(bufs[i] + offset, pktlen, mmsg[i].msg_hdr.msg_name, - mmsg[i].msg_hdr.msg_namelen, 0, userp); - if(result) - goto out; - } + result = recv_cb(bufs[i], mmsg[i].msg_len, gso_size, + mmsg[i].msg_hdr.msg_name, + mmsg[i].msg_hdr.msg_namelen, 0, userp); + if(result) + goto out; + pkts += (mmsg[i].msg_len + gso_size - 1) / gso_size; } } @@ -481,11 +479,11 @@ static CURLcode recvmsg_packets(struct Curl_cfilter *cf, struct Curl_easy *data, struct cf_quic_ctx *qctx, size_t max_pkts, - vquic_recv_pkt_cb *recv_cb, void *userp) + vquic_recv_pkts_cb *recv_cb, void *userp) { struct iovec msg_iov; struct msghdr msg; - uint8_t buf[64*1024]; + uint8_t buf[64 * 1024]; struct sockaddr_storage remote_addr; size_t total_nread, pkts, calls; ssize_t rc; @@ -494,8 +492,6 @@ static CURLcode recvmsg_packets(struct Curl_cfilter *cf, CURLcode result = CURLE_OK; uint8_t msg_ctrl[CMSG_SPACE(sizeof(int))]; size_t gso_size; - size_t pktlen; - size_t offset, to; DEBUGASSERT(max_pkts > 0); for(pkts = 0, total_nread = 0, calls = 0; pkts < max_pkts;) { @@ -514,7 +510,7 @@ static CURLcode recvmsg_packets(struct Curl_cfilter *cf, while((rc = recvmsg(qctx->sockfd, &msg, 0)) == -1 && (SOCKERRNO == SOCKEINTR || SOCKERRNO == SOCKEMSGSIZE)) ; - if(rc == -1) { + if(!curlx_sztouz(rc, &nread)) { if(SOCKERRNO == EAGAIN || SOCKERRNO == SOCKEWOULDBLOCK) { goto out; } @@ -528,34 +524,27 @@ static CURLcode recvmsg_packets(struct Curl_cfilter *cf, } curlx_strerror(SOCKERRNO, errstr, sizeof(errstr)); failf(data, "QUIC: recvmsg() unexpectedly returned %zd (errno=%d; %s)", - rc, SOCKERRNO, errstr); + rc, SOCKERRNO, errstr); result = CURLE_RECV_ERROR; goto out; } - nread = (size_t)rc; total_nread += nread; ++calls; + /* A 0-length UDP packet is no QUIC packet */ + if(!nread) + continue; + gso_size = vquic_msghdr_get_udp_gro(&msg); - if(gso_size == 0) { + if(gso_size == 0) gso_size = nread; - } - - for(offset = 0; offset < nread; offset = to) { - ++pkts; - - to = offset + gso_size; - if(to > nread) - pktlen = nread - offset; - else - pktlen = gso_size; - result = - recv_cb(buf + offset, pktlen, msg.msg_name, msg.msg_namelen, 0, userp); - if(result) - goto out; - } + result = recv_cb(buf, nread, gso_size, + msg.msg_name, msg.msg_namelen, 0, userp); + if(result) + goto out; + pkts += (nread + gso_size - 1) / gso_size; } out: @@ -570,25 +559,25 @@ static CURLcode recvfrom_packets(struct Curl_cfilter *cf, struct Curl_easy *data, struct cf_quic_ctx *qctx, size_t max_pkts, - vquic_recv_pkt_cb *recv_cb, void *userp) + vquic_recv_pkts_cb *recv_cb, void *userp) { - uint8_t buf[64*1024]; + uint8_t buf[64 * 1024]; int bufsize = (int)sizeof(buf); struct sockaddr_storage remote_addr; socklen_t remote_addrlen = sizeof(remote_addr); - size_t total_nread, pkts, calls = 0; - ssize_t nread; + size_t total_nread, pkts, calls = 0, nread; + ssize_t rv; char errstr[STRERROR_LEN]; CURLcode result = CURLE_OK; DEBUGASSERT(max_pkts > 0); for(pkts = 0, total_nread = 0; pkts < max_pkts;) { - while((nread = recvfrom(qctx->sockfd, (char *)buf, bufsize, 0, - (struct sockaddr *)&remote_addr, - &remote_addrlen)) == -1 && + while((rv = recvfrom(qctx->sockfd, (char *)buf, bufsize, 0, + (struct sockaddr *)&remote_addr, + &remote_addrlen)) == -1 && (SOCKERRNO == SOCKEINTR || SOCKERRNO == SOCKEMSGSIZE)) ; - if(nread == -1) { + if(!curlx_sztouz(rv, &nread)) { if(SOCKERRNO == EAGAIN || SOCKERRNO == SOCKEWOULDBLOCK) { CURL_TRC_CF(data, cf, "ingress, recvfrom -> EAGAIN"); goto out; @@ -603,15 +592,20 @@ static CURLcode recvfrom_packets(struct Curl_cfilter *cf, } curlx_strerror(SOCKERRNO, errstr, sizeof(errstr)); failf(data, "QUIC: recvfrom() unexpectedly returned %zd (errno=%d; %s)", - nread, SOCKERRNO, errstr); + rv, SOCKERRNO, errstr); result = CURLE_RECV_ERROR; goto out; } ++pkts; ++calls; - total_nread += (size_t)nread; - result = recv_cb(buf, (size_t)nread, &remote_addr, remote_addrlen, + + /* A 0-length UDP packet is no QUIC packet */ + if(!nread) + continue; + + total_nread += nread; + result = recv_cb(buf, nread, nread, &remote_addr, remote_addrlen, 0, userp); if(result) goto out; @@ -629,7 +623,7 @@ CURLcode vquic_recv_packets(struct Curl_cfilter *cf, struct Curl_easy *data, struct cf_quic_ctx *qctx, size_t max_pkts, - vquic_recv_pkt_cb *recv_cb, void *userp) + vquic_recv_pkts_cb *recv_cb, void *userp) { CURLcode result; #ifdef HAVE_SENDMMSG @@ -683,12 +677,16 @@ CURLcode Curl_qlogdir(struct Curl_easy *data, if(!result) { int qlogfd = curlx_open(curlx_dyn_ptr(&fname), O_WRONLY | O_CREAT | CURL_O_BINARY, - data->set.new_file_perms); + data->set.new_file_perms +#ifdef _WIN32 + & (_S_IREAD | _S_IWRITE) +#endif + ); if(qlogfd != -1) *qlogfdp = qlogfd; } curlx_dyn_free(&fname); - free(qlog_dir); + curlx_free(qlog_dir); if(result) return result; } @@ -700,7 +698,7 @@ CURLcode Curl_cf_quic_create(struct Curl_cfilter **pcf, struct Curl_easy *data, struct connectdata *conn, const struct Curl_addrinfo *ai, - int transport) + uint8_t transport) { (void)transport; DEBUGASSERT(transport == TRNSPRT_QUIC); diff --git a/lib/vquic/vquic.h b/lib/vquic/vquic.h index 0f81334f2937..fa2c0d4e816e 100644 --- a/lib/vquic/vquic.h +++ b/lib/vquic/vquic.h @@ -40,12 +40,11 @@ CURLcode Curl_qlogdir(struct Curl_easy *data, size_t scidlen, int *qlogfdp); - CURLcode Curl_cf_quic_create(struct Curl_cfilter **pcf, struct Curl_easy *data, struct connectdata *conn, const struct Curl_addrinfo *ai, - int transport); + uint8_t transport); extern struct Curl_cftype Curl_cft_http3; diff --git a/lib/vquic/vquic_int.h b/lib/vquic/vquic_int.h index 38189beb7038..82f22b45a88f 100644 --- a/lib/vquic/vquic_int.h +++ b/lib/vquic/vquic_int.h @@ -29,35 +29,40 @@ #ifdef USE_HTTP3 -#define MAX_PKT_BURST 10 +#define MAX_PKT_BURST 10 #define MAX_UDP_PAYLOAD_SIZE 1452 struct cf_quic_ctx { - curl_socket_t sockfd; /* connected UDP socket */ + curl_socket_t sockfd; /* connected UDP socket */ struct sockaddr_storage local_addr; /* address socket is bound to */ - 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 */ + 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 */ + int wblock_percent; /* percent of writes doing EAGAIN */ #endif BIT(got_first_byte); /* if first byte was received */ - BIT(no_gso); /* do not use gso on sending */ + BIT(no_gso); /* do not use gso on sending */ }; -#define H3_STREAM_CTX(ctx,data) \ - (data ? Curl_uint_hash_get(&(ctx)->streams, (data)->mid) : NULL) +#define H3_STREAM_CTX(ctx, data) \ + (data ? Curl_uint32_hash_get(&(ctx)->streams, (data)->mid) : NULL) -CURLcode vquic_ctx_init(struct cf_quic_ctx *qctx); +CURLcode vquic_ctx_init(struct Curl_easy *data, + 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_ctx_set_time(struct cf_quic_ctx *qctx, + const struct curltime *pnow); + +void vquic_ctx_update_time(struct cf_quic_ctx *qctx, + const struct curltime *pnow); void vquic_push_blocked_pkt(struct Curl_cfilter *cf, struct cf_quic_ctx *qctx, @@ -77,17 +82,17 @@ CURLcode vquic_send_tail_split(struct Curl_cfilter *cf, struct Curl_easy *data, CURLcode vquic_flush(struct Curl_cfilter *cf, struct Curl_easy *data, struct cf_quic_ctx *qctx); - -typedef CURLcode vquic_recv_pkt_cb(const unsigned char *pkt, size_t pktlen, - struct sockaddr_storage *remote_addr, - socklen_t remote_addrlen, int ecn, - void *userp); +typedef CURLcode vquic_recv_pkts_cb(const unsigned char *buf, size_t buflen, + size_t gso_size, + struct sockaddr_storage *remote_addr, + socklen_t remote_addrlen, int ecn, + void *userp); CURLcode vquic_recv_packets(struct Curl_cfilter *cf, struct Curl_easy *data, struct cf_quic_ctx *qctx, size_t max_pkts, - vquic_recv_pkt_cb *recv_cb, void *userp); + vquic_recv_pkts_cb *recv_cb, void *userp); #endif /* !USE_HTTP3 */ diff --git a/lib/vssh/libssh.c b/lib/vssh/libssh.c index 3741db20dc63..7d5905c83d75 100644 --- a/lib/vssh/libssh.c +++ b/lib/vssh/libssh.c @@ -29,8 +29,6 @@ #ifdef USE_LIBSSH -#include - #ifdef HAVE_NETINET_IN_H #include #endif @@ -45,29 +43,22 @@ #include #endif -#include #include "../urldata.h" #include "../sendf.h" +#include "../curl_trc.h" #include "../hostip.h" #include "../progress.h" #include "../transfer.h" -#include "../escape.h" #include "../http.h" /* for HTTP proxy tunnel stuff */ #include "ssh.h" #include "../url.h" -#include "../speedcheck.h" -#include "../getinfo.h" -#include "../strdup.h" -#include "../vtls/vtls.h" #include "../cfilters.h" #include "../connect.h" #include "../parsedate.h" /* for the week day and month names */ -#include "../sockaddr.h" /* required for Curl_sockaddr_storage */ #include "../curlx/strparse.h" #include "../multiif.h" #include "../select.h" -#include "../curlx/warnless.h" -#include "curl_path.h" +#include "vssh.h" #ifdef HAVE_UNISTD_H #include @@ -76,18 +67,14 @@ #include #endif -/* The last 2 #include files should be in this order */ -#include "../curl_memory.h" -#include "../memdebug.h" - /* A recent macro provided by libssh. Or make our own. */ #ifndef SSH_STRING_FREE_CHAR -#define SSH_STRING_FREE_CHAR(x) \ - do { \ - if(x) { \ - ssh_string_free_char(x); \ - x = NULL; \ - } \ +#define SSH_STRING_FREE_CHAR(x) \ + do { \ + if(x) { \ + ssh_string_free_char(x); \ + x = NULL; \ + } \ } while(0) #endif @@ -119,10 +106,9 @@ static CURLcode sftp_doing(struct Curl_easy *data, static CURLcode sftp_disconnect(struct Curl_easy *data, struct connectdata *conn, bool dead); -static -CURLcode sftp_perform(struct Curl_easy *data, - bool *connected, - bool *dophase_done); +static CURLcode sftp_perform(struct Curl_easy *data, + bool *connected, + bool *dophase_done); static CURLcode myssh_pollset(struct Curl_easy *data, struct easy_pollset *ps); @@ -160,7 +146,8 @@ const struct Curl_handler Curl_handler_scp = { PORT_SSH, /* defport */ CURLPROTO_SCP, /* protocol */ CURLPROTO_SCP, /* family */ - PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | PROTOPT_NOURLQUERY /* flags */ + PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | /* flags */ + PROTOPT_NOURLQUERY | PROTOPT_CONN_REUSE }; /* @@ -189,55 +176,38 @@ const struct Curl_handler Curl_handler_sftp = { PORT_SSH, /* defport */ CURLPROTO_SFTP, /* protocol */ CURLPROTO_SFTP, /* family */ - PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION - | PROTOPT_NOURLQUERY /* flags */ + PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | /* flags */ + PROTOPT_NOURLQUERY | PROTOPT_CONN_REUSE }; static CURLcode sftp_error_to_CURLE(int err) { switch(err) { - case SSH_FX_OK: - return CURLE_OK; + case SSH_FX_OK: + return CURLE_OK; - case SSH_FX_NO_SUCH_FILE: - case SSH_FX_NO_SUCH_PATH: - return CURLE_REMOTE_FILE_NOT_FOUND; + case SSH_FX_NO_SUCH_FILE: + case SSH_FX_NO_SUCH_PATH: + return CURLE_REMOTE_FILE_NOT_FOUND; - case SSH_FX_PERMISSION_DENIED: - case SSH_FX_WRITE_PROTECT: - return CURLE_REMOTE_ACCESS_DENIED; + case SSH_FX_PERMISSION_DENIED: + case SSH_FX_WRITE_PROTECT: + return CURLE_REMOTE_ACCESS_DENIED; - case SSH_FX_FILE_ALREADY_EXISTS: - return CURLE_REMOTE_FILE_EXISTS; + case SSH_FX_FILE_ALREADY_EXISTS: + return CURLE_REMOTE_FILE_EXISTS; - default: - break; + default: + break; } return CURLE_SSH; } -#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) -#define myssh_to(x,y,z) myssh_set_state(x,y,z, __LINE__) -#else -#define myssh_to(x,y,z) myssh_set_state(x,y,z) -#endif - -/* - * SSH State machine related code - */ -/* This is the ONLY way to change SSH state! */ -static void myssh_set_state(struct Curl_easy *data, - struct ssh_conn *sshc, - sshstate nowstate -#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) - , int lineno -#endif - ) +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static const char *myssh_statename(sshstate state) { -#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) - /* for debug purposes */ - static const char *const names[] = { + static const char * const names[] = { "SSH_STOP", "SSH_INIT", "SSH_S_STARTUP", @@ -299,15 +269,33 @@ static void myssh_set_state(struct Curl_easy *data, "SSH_SESSION_FREE", "QUIT" }; + /* a precaution to make sure the lists are in sync */ + DEBUGASSERT(CURL_ARRAYSIZE(names) == SSH_LAST); + return ((size_t)state < CURL_ARRAYSIZE(names)) ? names[state] : ""; +} +#else +#define myssh_statename(x) "" +#endif /* !CURL_DISABLE_VERBOSE_STRINGS */ +#define myssh_to(x, y, z) myssh_set_state(x, y, z) +/* + * SSH State machine related code + */ +/* This is the ONLY way to change SSH state! */ +static void myssh_set_state(struct Curl_easy *data, + struct ssh_conn *sshc, + sshstate nowstate) +{ +#ifndef CURL_DISABLE_VERBOSE_STRINGS if(sshc->state != nowstate) { - infof(data, "SSH %p state change from %s to %s (line %d)", - (void *) sshc, names[sshc->state], names[nowstate], - lineno); + CURL_TRC_SSH(data, "[%s] -> [%s]", + myssh_statename(sshc->state), + myssh_statename(nowstate)); } -#endif +#else (void)data; +#endif sshc->state = nowstate; } @@ -333,8 +321,7 @@ static int myssh_is_known(struct Curl_easy *data, struct ssh_conn *sshc) enum curl_khmatch keymatch; struct curl_khkey foundkey; struct curl_khkey *knownkeyp = NULL; - curl_sshkeycallback func = - data->set.ssh_keyfunc; + curl_sshkeycallback func = data->set.ssh_keyfunc; struct ssh_knownhosts_entry *knownhostsentry = NULL; struct curl_khkey knownkey; @@ -348,8 +335,7 @@ static int myssh_is_known(struct Curl_easy *data, struct ssh_conn *sshc) char md5buffer[33]; const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5]; - rc = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_MD5, - &hash, &hlen); + rc = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_MD5, &hash, &hlen); if(rc != SSH_OK || hlen != 16) { failf(data, "Denied establishing ssh session: md5 fingerprint not available"); @@ -357,7 +343,7 @@ static int myssh_is_known(struct Curl_easy *data, struct ssh_conn *sshc) } for(i = 0; i < 16; i++) - curl_msnprintf(&md5buffer[i*2], 3, "%02x", (unsigned char)hash[i]); + curl_msnprintf(&md5buffer[i * 2], 3, "%02x", (unsigned char)hash[i]); infof(data, "SSH MD5 fingerprint: %s", md5buffer); @@ -466,7 +452,7 @@ static int myssh_is_known(struct Curl_easy *data, struct ssh_conn *sshc) Curl_set_in_callback(data, TRUE); rc = func(data, knownkeyp, /* from the knownhosts file */ - &foundkey, /* from the remote host */ + &foundkey, /* from the remote host */ keymatch, data->set.ssh_keyfunc_userp); Curl_set_in_callback(data, FALSE); @@ -495,10 +481,12 @@ static int myssh_is_known(struct Curl_easy *data, struct ssh_conn *sshc) cleanup: if(found_base64) { - (free)(found_base64); + /* !checksrc! disable BANNEDFUNC 1 */ + free(found_base64); /* allocated by libssh, deallocate with system free */ } if(known_base64) { - (free)(known_base64); + /* !checksrc! disable BANNEDFUNC 1 */ + free(known_base64); /* allocated by libssh, deallocate with system free */ } if(hash) ssh_clean_pubkey_hash(&hash); @@ -522,8 +510,7 @@ static int myssh_to_SFTP_CLOSE(struct Curl_easy *data, struct ssh_conn *sshc) { myssh_to(data, sshc, SSH_SFTP_CLOSE); - sshc->actualcode = - sftp_error_to_CURLE(sftp_get_error(sshc->sftp_session)); + sshc->actualcode = sftp_error_to_CURLE(sftp_get_error(sshc->sftp_session)); return SSH_ERROR; } @@ -609,13 +596,13 @@ static int myssh_in_SFTP_READDIR(struct Curl_easy *data, } result = Curl_client_write(data, CLIENTWRITE_BODY, tmpLine, sshc->readdir_len + 1); - free(tmpLine); + curlx_free(tmpLine); if(result) { myssh_to(data, sshc, SSH_STOP); + sshc->actualcode = result; return SSH_NO_ERROR; } - } else { if(curlx_dyn_add(&sshc->readdir_buf, sshc->readdir_longentry)) { @@ -686,8 +673,7 @@ static int myssh_in_SFTP_READDIR_LINK(struct Curl_easy *data, Curl_safefree(sshc->readdir_linkPath); - if(curlx_dyn_addf(&sshc->readdir_buf, " -> %s", - sshc->readdir_filename)) { + if(curlx_dyn_addf(&sshc->readdir_buf, " -> %s", sshc->readdir_filename)) { /* Not using: * return myssh_to_SFTP_CLOSE(data, sshc); * @@ -790,7 +776,7 @@ static int myssh_in_SFTP_QUOTE_STATVFS(struct Curl_easy *data, if(!result) { result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp)); - free(tmp); + curlx_free(tmp); } if(result) { myssh_to(data, sshc, SSH_SFTP_CLOSE); @@ -810,56 +796,56 @@ static int myssh_auth_interactive(struct connectdata *conn, restart: switch(sshc->kbd_state) { - case 0: - rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL); - if(rc == SSH_AUTH_AGAIN) - return SSH_AGAIN; + case 0: + rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL); + if(rc == SSH_AUTH_AGAIN) + return SSH_AGAIN; - if(rc != SSH_AUTH_INFO) - return SSH_ERROR; + if(rc != SSH_AUTH_INFO) + return SSH_ERROR; - nprompts = ssh_userauth_kbdint_getnprompts(sshc->ssh_session); - if(nprompts != 1) - return SSH_ERROR; + nprompts = ssh_userauth_kbdint_getnprompts(sshc->ssh_session); + if(nprompts != 1) + return SSH_ERROR; - rc = ssh_userauth_kbdint_setanswer(sshc->ssh_session, 0, conn->passwd); - if(rc < 0) - return SSH_ERROR; + rc = ssh_userauth_kbdint_setanswer(sshc->ssh_session, 0, conn->passwd); + if(rc < 0) + return SSH_ERROR; - FALLTHROUGH(); - case 1: - sshc->kbd_state = 1; + FALLTHROUGH(); + case 1: + sshc->kbd_state = 1; - rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL); - if(rc == SSH_AUTH_AGAIN) - return SSH_AGAIN; - else if(rc == SSH_AUTH_SUCCESS) - rc = SSH_OK; - else if(rc == SSH_AUTH_INFO) { - nprompts = ssh_userauth_kbdint_getnprompts(sshc->ssh_session); - if(nprompts) - return SSH_ERROR; + rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL); + if(rc == SSH_AUTH_AGAIN) + return SSH_AGAIN; + else if(rc == SSH_AUTH_SUCCESS) + rc = SSH_OK; + else if(rc == SSH_AUTH_INFO) { + nprompts = ssh_userauth_kbdint_getnprompts(sshc->ssh_session); + if(nprompts) + return SSH_ERROR; - sshc->kbd_state = 2; - goto restart; - } - else - rc = SSH_ERROR; - break; - case 2: sshc->kbd_state = 2; + goto restart; + } + else + rc = SSH_ERROR; + break; + case 2: + sshc->kbd_state = 2; - rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL); - if(rc == SSH_AUTH_AGAIN) - return SSH_AGAIN; - else if(rc == SSH_AUTH_SUCCESS) - rc = SSH_OK; - else - rc = SSH_ERROR; + rc = ssh_userauth_kbdint(sshc->ssh_session, NULL, NULL); + if(rc == SSH_AUTH_AGAIN) + return SSH_AGAIN; + else if(rc == SSH_AUTH_SUCCESS) + rc = SSH_OK; + else + rc = SSH_ERROR; - break; - default: - return SSH_ERROR; + break; + default: + return SSH_ERROR; } sshc->kbd_state = 0; @@ -892,7 +878,7 @@ static int myssh_in_S_STARTUP(struct Curl_easy *data, myssh_block2waitfor(conn, sshc, (rc == SSH_AGAIN)); if(rc == SSH_AGAIN) { - DEBUGF(infof(data, "ssh_connect -> EAGAIN")); + CURL_TRC_SSH(data, "connect -> EAGAIN"); } else if(rc != SSH_OK) { failf(data, "Failure establishing ssh session"); @@ -969,8 +955,7 @@ static int myssh_in_AUTH_PKEY_INIT(struct Curl_easy *data, * (2) use the "default" keys. */ if(data->set.str[STRING_SSH_PRIVATE_KEY]) { if(sshc->pubkey && !data->set.ssl.key_passwd) { - rc = ssh_userauth_try_publickey(sshc->ssh_session, NULL, - sshc->pubkey); + rc = ssh_userauth_try_publickey(sshc->ssh_session, NULL, sshc->pubkey); if(rc == SSH_AUTH_AGAIN) return SSH_AGAIN; @@ -995,7 +980,7 @@ static int myssh_in_AUTH_PKEY_INIT(struct Curl_easy *data, } else { rc = ssh_userauth_publickey_auto(sshc->ssh_session, NULL, - data->set.ssl.key_passwd); + data->set.ssl.key_passwd); if(rc == SSH_AUTH_AGAIN) return SSH_AGAIN; @@ -1140,14 +1125,13 @@ static int myssh_in_UPLOAD_INIT(struct Curl_easy *data, attrs = sftp_stat(sshc->sftp_session, sshp->path); if(attrs) { curl_off_t size = attrs->size; + sftp_attributes_free(attrs); if(size < 0) { failf(data, "Bad file size (%" FMT_OFF_T ")", size); rc = myssh_to_ERROR(data, sshc, CURLE_BAD_DOWNLOAD_RESUME); return rc; } - data->state.resume_from = attrs->size; - - sftp_attributes_free(attrs); + data->state.resume_from = size; } else { data->state.resume_from = 0; @@ -1169,7 +1153,7 @@ static int myssh_in_UPLOAD_INIT(struct Curl_easy *data, } else /* Clear file before writing (normal behavior) */ - flags = O_WRONLY|O_CREAT|O_TRUNC; + flags = O_WRONLY | O_CREAT | O_TRUNC; if(sshc->sftp_file) sftp_close(sshc->sftp_file); @@ -1217,7 +1201,7 @@ static int myssh_in_UPLOAD_INIT(struct Curl_easy *data, } /* seekerr == CURL_SEEKFUNC_CANTSEEK (cannot seek to offset) */ do { - char scratch[4*1024]; + char scratch[4 * 1024]; size_t readthisamountnow = (data->state.resume_from - passed > (curl_off_t)sizeof(scratch)) ? @@ -1265,10 +1249,6 @@ static int myssh_in_UPLOAD_INIT(struct Curl_easy *data, /* not set by Curl_xfer_setup to preserve keepon bits */ data->conn->recv_idx = FIRSTSOCKET; - /* store this original bitmask setup to use later on if we cannot - figure out a "real" bitmask */ - sshc->orig_waitfor = data->req.keepon; - /* since we do not really wait for anything at this point, we want the state machine to move on as soon as possible so we mark this as dirty */ Curl_multi_mark_dirty(data); @@ -1332,44 +1312,11 @@ static int myssh_in_SFTP_DOWNLOAD_STAT(struct Curl_easy *data, return myssh_to_ERROR(data, sshc, CURLE_BAD_DOWNLOAD_RESUME); } if(data->state.use_range) { - curl_off_t from, to; - const char *p = data->state.range; - int from_t, to_t; - - from_t = curlx_str_number(&p, &from, CURL_OFF_T_MAX); - if(from_t == STRE_OVERFLOW) - return myssh_to_ERROR(data, sshc, CURLE_RANGE_ERROR); - - curlx_str_passblanks(&p); - (void)curlx_str_single(&p, '-'); - - to_t = curlx_str_numblanks(&p, &to); - if(to_t == STRE_OVERFLOW) - return myssh_to_ERROR(data, sshc, CURLE_RANGE_ERROR); - - if((to_t == STRE_NO_NUM) || (to >= size)) { - to = size - 1; - } - - if(from_t == STRE_NO_NUM) { - /* from is relative to end of file */ - from = size - to; - to = size - 1; - } - if(from > size) { - failf(data, "Offset (%" FMT_OFF_T ") was beyond file size (%" - FMT_OFF_T ")", from, size); - return myssh_to_ERROR(data, sshc, CURLE_BAD_DOWNLOAD_RESUME); - } - if(from > to) { - from = to; - size = 0; - } - else { - if((to - from) == CURL_OFF_T_MAX) - return myssh_to_ERROR(data, sshc, CURLE_RANGE_ERROR); - size = to - from + 1; - } + curl_off_t from; + CURLcode result = Curl_ssh_range(data, data->state.range, size, + &from, &size); + if(result) + return myssh_to_ERROR(data, sshc, result); rc = sftp_seek64(sshc->sftp_file, from); if(rc) @@ -1403,8 +1350,7 @@ static int myssh_in_SFTP_DOWNLOAD_STAT(struct Curl_easy *data, /* Now store the number of bytes we are expected to download */ data->req.size = size - data->state.resume_from; data->req.maxdownload = size - data->state.resume_from; - Curl_pgrsSetDownloadSize(data, - size - data->state.resume_from); + Curl_pgrsSetDownloadSize(data, size - data->state.resume_from); rc = sftp_seek64(sshc->sftp_file, data->state.resume_from); if(rc) @@ -1440,7 +1386,7 @@ static int myssh_in_SFTP_CLOSE(struct Curl_easy *data, } Curl_safefree(sshp->path); - DEBUGF(infof(data, "SFTP DONE done")); + CURL_TRC_SSH(data, "SFTP DONE done"); /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT After nextstate is executed, the control should come back to @@ -1515,8 +1461,8 @@ static int myssh_in_SFTP_REALPATH(struct Curl_easy *data, if(!sshc->homedir) return myssh_to_ERROR(data, sshc, CURLE_COULDNT_CONNECT); - free(data->state.most_recent_ftp_entrypath); - data->state.most_recent_ftp_entrypath = strdup(sshc->homedir); + curlx_free(data->state.most_recent_ftp_entrypath); + data->state.most_recent_ftp_entrypath = curlx_strdup(sshc->homedir); if(!data->state.most_recent_ftp_entrypath) return myssh_to_ERROR(data, sshc, CURLE_OUT_OF_MEMORY); @@ -1524,7 +1470,7 @@ static int myssh_in_SFTP_REALPATH(struct Curl_easy *data, we get the homedir here, we get the "workingpath" in the DO action since the homedir will remain the same between request but the working path will not. */ - DEBUGF(infof(data, "SSH CONNECT phase done")); + CURL_TRC_SSH(data, "CONNECT phase done"); myssh_to(data, sshc, SSH_STOP); return SSH_NO_ERROR; } @@ -1610,11 +1556,11 @@ static int myssh_in_SFTP_QUOTE(struct Curl_easy *data, Curl_debug(data, CURLINFO_HEADER_OUT, "PWD\n", 4); Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp)); - /* this sends an FTP-like "header" to the header callback so that the - current directory can be read very similar to how it is read when + /* this sends an FTP-like "header" to the header callback so that + the current directory can be read similar to how it is read when using ordinary FTP. */ result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp)); - free(tmp); + curlx_free(tmp); if(result) { myssh_to(data, sshc, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; @@ -1713,7 +1659,7 @@ static int myssh_in_SFTP_QUOTE(struct Curl_easy *data, else if(!strncmp(cmd, "mkdir ", 6)) { if(*cp) return return_quote_error(data, sshc); - /* create dir */ + /* create directory */ myssh_to(data, sshc, SSH_SFTP_QUOTE_MKDIR); return SSH_NO_ERROR; } @@ -1739,7 +1685,7 @@ static int myssh_in_SFTP_QUOTE(struct Curl_easy *data, return SSH_NO_ERROR; } else if(!strncmp(cmd, "rmdir ", 6)) { - /* delete dir */ + /* delete directory */ if(*cp) return return_quote_error(data, sshc); myssh_to(data, sshc, SSH_SFTP_QUOTE_RMDIR); @@ -1896,7 +1842,7 @@ static int myssh_in_SFTP_QUOTE_STAT(struct Curl_easy *data, return SSH_NO_ERROR; } if(date > UINT_MAX) - /* because the liubssh API can't deal with a larger value */ + /* because the liubssh API cannot deal with a larger value */ date = UINT_MAX; if(!strncmp(cmd, "atime", 5)) sshc->quote_attrs->atime = (uint32_t)date; @@ -1911,6 +1857,18 @@ static int myssh_in_SFTP_QUOTE_STAT(struct Curl_easy *data, return SSH_NO_ERROR; } +static void conn_forget_socket(struct Curl_easy *data, int sockindex) +{ + struct connectdata *conn = data->conn; + if(conn && CONN_SOCK_IDX_VALID(sockindex)) { + struct Curl_cfilter *cf = conn->cfilter[sockindex]; + if(cf) + (void)Curl_conn_cf_cntrl(cf, data, TRUE, CF_CTRL_FORGET_SOCKET, 0, NULL); + fake_sclose(conn->sock[sockindex]); + conn->sock[sockindex] = CURL_SOCKET_BAD; + } +} + /* * ssh_statemach_act() runs the SSH state machine as far as it can without * blocking and without reaching the end. The data the pointer 'block' points @@ -1981,13 +1939,15 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, rc = myssh_in_SFTP_REALPATH(data, sshc); break; case SSH_SFTP_QUOTE_INIT: - rc = myssh_in_SFTP_QUOTE_INIT(data, sshc, sshp); + rc = sshp ? myssh_in_SFTP_QUOTE_INIT(data, sshc, sshp) : + CURLE_FAILED_INIT; break; case SSH_SFTP_POSTQUOTE_INIT: rc = myssh_in_SFTP_POSTQUOTE_INIT(data, sshc); break; case SSH_SFTP_QUOTE: - rc = myssh_in_SFTP_QUOTE(data, sshc, sshp); + rc = sshp ? myssh_in_SFTP_QUOTE(data, sshc, sshp) : + CURLE_FAILED_INIT; break; case SSH_SFTP_NEXT_QUOTE: rc = myssh_in_SFTP_NEXT_QUOTE(data, sshc); @@ -2092,8 +2052,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, break; if(rc && !sshc->acceptfail) { Curl_safefree(sshc->quote_path1); - failf(data, "rm command failed: %s", - ssh_get_error(sshc->ssh_session)); + failf(data, "rm command failed: %s", ssh_get_error(sshc->ssh_session)); myssh_to(data, sshc, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; sshc->actualcode = CURLE_QUOTE_ERROR; @@ -2117,7 +2076,10 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, case SSH_SFTP_FILETIME: { sftp_attributes attrs; - + if(!sshp) { + result = CURLE_FAILED_INIT; + break; + } attrs = sftp_stat(sshc->sftp_session, sshp->path); if(attrs) { data->info.filetime = attrs->mtime; @@ -2131,20 +2093,27 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, case SSH_SFTP_TRANS_INIT: if(data->state.upload) myssh_to(data, sshc, SSH_SFTP_UPLOAD_INIT); - else { - if(sshp->path[strlen(sshp->path)-1] == '/') + else if(sshp) { + if(sshp->path[strlen(sshp->path) - 1] == '/') myssh_to(data, sshc, SSH_SFTP_READDIR_INIT); else myssh_to(data, sshc, SSH_SFTP_DOWNLOAD_INIT); } + else + result = CURLE_FAILED_INIT; break; case SSH_SFTP_UPLOAD_INIT: - rc = myssh_in_UPLOAD_INIT(data, sshc, sshp); + rc = sshp ? myssh_in_UPLOAD_INIT(data, sshc, sshp) : + CURLE_FAILED_INIT; break; case SSH_SFTP_CREATE_DIRS_INIT: - if(strlen(sshp->path) > 1) { + if(!sshp) { + result = CURLE_FAILED_INIT; + break; + } + else if(strlen(sshp->path) > 1) { sshc->slash_pos = sshp->path + 1; /* ignore the leading '/' */ myssh_to(data, sshc, SSH_SFTP_CREATE_DIRS); } @@ -2155,7 +2124,11 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, case SSH_SFTP_CREATE_DIRS: sshc->slash_pos = strchr(sshc->slash_pos, '/'); - if(sshc->slash_pos) { + if(!sshp) { + result = CURLE_FAILED_INIT; + break; + } + else if(sshc->slash_pos) { *sshc->slash_pos = 0; infof(data, "Creating directory '%s'", sshp->path); @@ -2167,15 +2140,19 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, case SSH_SFTP_CREATE_DIRS_MKDIR: /* 'mode' - parameter is preliminary - default to 0644 */ + if(!sshp) { + result = CURLE_FAILED_INIT; + break; + } rc = sftp_mkdir(sshc->sftp_session, sshp->path, (mode_t)data->set.new_directory_perms); *sshc->slash_pos = '/'; ++sshc->slash_pos; if(rc < 0) { /* - * Abort if failure was not that the dir already exists or the - * permission was denied (creation might succeed further down the - * path) - retry on unspecific FAILURE also + * Abort if failure was not that the directory already exists or + * the permission was denied (creation might succeed further down + * the path) - retry on unspecific FAILURE also */ err = sftp_get_error(sshc->sftp_session); if((err != SSH_FX_FILE_ALREADY_EXISTS) && @@ -2190,10 +2167,12 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, break; case SSH_SFTP_READDIR_INIT: - rc = myssh_in_SFTP_READDIR_INIT(data, sshc, sshp); + rc = sshp ? myssh_in_SFTP_READDIR_INIT(data, sshc, sshp) : + CURLE_FAILED_INIT; break; case SSH_SFTP_READDIR: - rc = myssh_in_SFTP_READDIR(data, sshc, sshp); + rc = sshp ? myssh_in_SFTP_READDIR(data, sshc, sshp) : + CURLE_FAILED_INIT; break; case SSH_SFTP_READDIR_LINK: rc = myssh_in_SFTP_READDIR_LINK(data, sshc); @@ -2205,19 +2184,25 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, rc = myssh_in_SFTP_READDIR_DONE(data, sshc); break; case SSH_SFTP_DOWNLOAD_INIT: - rc = myssh_in_SFTP_DOWNLOAD_INIT(data, sshc, sshp); + rc = sshp ? myssh_in_SFTP_DOWNLOAD_INIT(data, sshc, sshp) : + CURLE_FAILED_INIT; break; case SSH_SFTP_DOWNLOAD_STAT: rc = myssh_in_SFTP_DOWNLOAD_STAT(data, sshc); break; case SSH_SFTP_CLOSE: - rc = myssh_in_SFTP_CLOSE(data, sshc, sshp); + rc = sshp ? myssh_in_SFTP_CLOSE(data, sshc, sshp) : + CURLE_FAILED_INIT; break; case SSH_SFTP_SHUTDOWN: rc = myssh_in_SFTP_SHUTDOWN(data, sshc); break; case SSH_SCP_TRANS_INIT: + if(!sshp) { + result = CURLE_FAILED_INIT; + break; + } result = Curl_getworkingpath(data, sshc->homedir, &sshp->path); if(result) { sshc->actualcode = result; @@ -2254,7 +2239,10 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, break; case SSH_SCP_UPLOAD_INIT: - + if(!sshp) { + result = CURLE_FAILED_INIT; + break; + } rc = ssh_scp_init(sshc->scp_session); if(rc != SSH_OK) { err_msg = ssh_get_error(sshc->ssh_session); @@ -2280,10 +2268,6 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, /* not set by Curl_xfer_setup to preserve keepon bits */ data->conn->recv_idx = FIRSTSOCKET; - /* store this original bitmask setup to use later on if we cannot - figure out a "real" bitmask */ - sshc->orig_waitfor = data->req.keepon; - myssh_to(data, sshc, SSH_STOP); break; @@ -2301,26 +2285,26 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, FALLTHROUGH(); case SSH_SCP_DOWNLOAD: { - curl_off_t bytecount; + curl_off_t bytecount; - rc = ssh_scp_pull_request(sshc->scp_session); - if(rc != SSH_SCP_REQUEST_NEWFILE) { - err_msg = ssh_get_error(sshc->ssh_session); - failf(data, "%s", err_msg); - rc = myssh_to_ERROR(data, sshc, CURLE_REMOTE_FILE_NOT_FOUND); - break; - } + rc = ssh_scp_pull_request(sshc->scp_session); + if(rc != SSH_SCP_REQUEST_NEWFILE) { + err_msg = ssh_get_error(sshc->ssh_session); + failf(data, "%s", err_msg); + rc = myssh_to_ERROR(data, sshc, CURLE_REMOTE_FILE_NOT_FOUND); + break; + } - /* download data */ - bytecount = ssh_scp_request_get_size(sshc->scp_session); - data->req.maxdownload = (curl_off_t) bytecount; - Curl_xfer_setup_recv(data, FIRSTSOCKET, bytecount); + /* download data */ + bytecount = ssh_scp_request_get_size(sshc->scp_session); + data->req.maxdownload = (curl_off_t)bytecount; + Curl_xfer_setup_recv(data, FIRSTSOCKET, bytecount); - /* not set by Curl_xfer_setup to preserve keepon bits */ - conn->send_idx = 0; + /* not set by Curl_xfer_setup to preserve keepon bits */ + conn->send_idx = 0; - myssh_to(data, sshc, SSH_STOP); - break; + myssh_to(data, sshc, SSH_STOP); + break; } case SSH_SCP_DONE: if(data->state.upload) @@ -2352,7 +2336,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, ssh_scp_free(sshc->scp_session); sshc->scp_session = NULL; } - DEBUGF(infof(data, "SCP DONE phase complete")); + CURL_TRC_SSH(data, "SCP DONE phase complete"); ssh_set_blocking(sshc->ssh_session, 0); @@ -2382,7 +2366,7 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, /* conn->sock[FIRSTSOCKET] is closed by ssh_disconnect behind our back, tell the connection to forget about it. This libssh bug is fixed in 0.10.0. */ - Curl_conn_forget_socket(data, FIRSTSOCKET); + conn_forget_socket(data, FIRSTSOCKET); } SSH_STRING_FREE_CHAR(sshc->homedir); @@ -2406,10 +2390,10 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, sshc->nextstate = SSH_NO_STATE; myssh_to(data, sshc, SSH_STOP); break; - } - } while(!rc && (sshc->state != SSH_STOP)); - + /* break the loop only on STOP or SSH_AGAIN. If `rc` is some + * other error code, we will have progressed the state accordingly. */ + } while((rc != SSH_AGAIN) && (sshc->state != SSH_STOP)); if(rc == SSH_AGAIN) { /* we would block, we need to wait for the socket to be ready (in the @@ -2418,43 +2402,55 @@ static CURLcode myssh_statemach_act(struct Curl_easy *data, } if(!result && (sshc->state == SSH_STOP)) result = sshc->actualcode; - DEBUGF(infof(data, "SSH: myssh_statemach_act -> %d", result)); + CURL_TRC_SSH(data, "[%s] statemachine() -> %d, block=%d", + myssh_statename(sshc->state), result, *block); return result; } - /* called by the multi interface to figure out what socket(s) to wait for and for what actions in the DO_DONE, PERFORM and WAITPERFORM states */ static CURLcode myssh_pollset(struct Curl_easy *data, struct easy_pollset *ps) { - int flags = 0; struct connectdata *conn = data->conn; - if(conn->waitfor & KEEP_RECV) - flags |= CURL_POLL_IN; - if(conn->waitfor & KEEP_SEND) - flags |= CURL_POLL_OUT; - if(!conn->waitfor) - flags |= CURL_POLL_OUT; - return flags ? - Curl_pollset_change(data, ps, conn->sock[FIRSTSOCKET], flags, 0) : - CURLE_OK; + struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN); + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + int waitfor; + + if(!sshc || (sock == CURL_SOCKET_BAD)) + return CURLE_FAILED_INIT; + + waitfor = sshc->waitfor ? sshc->waitfor : data->req.keepon; + if(waitfor) { + int flags = 0; + if(waitfor & KEEP_RECV) + flags |= CURL_POLL_IN; + if(waitfor & KEEP_SEND) + flags |= CURL_POLL_OUT; + DEBUGASSERT(flags); + CURL_TRC_SSH(data, "pollset, flags=%x", flags); + return Curl_pollset_change(data, ps, sock, flags, 0); + } + /* While we still have a session, we listen incoming data. */ + if(sshc->ssh_session) + return Curl_pollset_change(data, ps, sock, CURL_POLL_IN, 0); + return CURLE_OK; } static void myssh_block2waitfor(struct connectdata *conn, struct ssh_conn *sshc, bool block) { + (void)conn; if(block) { int dir = ssh_get_poll_flags(sshc->ssh_session); /* translate the libssh define bits into our own bit defines */ - conn->waitfor = + sshc->waitfor = ((dir & SSH_READ_PENDING) ? KEEP_RECV : 0) | ((dir & SSH_WRITE_PENDING) ? KEEP_SEND : 0); } else - /* if it did not block, use the original set */ - conn->waitfor = sshc->orig_waitfor; + sshc->waitfor = 0; } /* called repeatedly until done from multi.c */ @@ -2487,23 +2483,19 @@ static CURLcode myssh_block_statemach(struct Curl_easy *data, while((sshc->state != SSH_STOP) && !result) { bool block; - timediff_t left = 1000; - struct curltime now = curlx_now(); + timediff_t left_ms = 1000; result = myssh_statemach_act(data, sshc, sshp, &block); if(result) break; if(!disconnect) { - if(Curl_pgrsUpdate(data)) - return CURLE_ABORTED_BY_CALLBACK; - - result = Curl_speedcheck(data, now); + result = Curl_pgrsCheck(data); if(result) break; - left = Curl_timeleft(data, NULL, FALSE); - if(left < 0) { + left_ms = Curl_timeleft_ms(data, FALSE); + if(left_ms < 0) { failf(data, "Operation timed out"); return CURLE_OPERATION_TIMEDOUT; } @@ -2512,10 +2504,8 @@ static CURLcode myssh_block_statemach(struct Curl_easy *data, if(block) { curl_socket_t fd_read = conn->sock[FIRSTSOCKET]; /* wait for the socket to become ready */ - (void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, - CURL_SOCKET_BAD, left > 1000 ? 1000 : left); + (void)SOCKET_READABLE(fd_read, left_ms > 1000 ? 1000 : left_ms); } - } return result; @@ -2527,7 +2517,7 @@ static void myssh_easy_dtor(void *key, size_t klen, void *entry) (void)key; (void)klen; Curl_safefree(sshp->path); - free(sshp); + curlx_free(sshp); } static void myssh_conn_dtor(void *key, size_t klen, void *entry) @@ -2536,7 +2526,7 @@ static void myssh_conn_dtor(void *key, size_t klen, void *entry) (void)key; (void)klen; sshc_cleanup(sshc); - free(sshc); + curlx_free(sshc); } /* @@ -2548,7 +2538,7 @@ static CURLcode myssh_setup_connection(struct Curl_easy *data, struct SSHPROTO *sshp; struct ssh_conn *sshc; - sshc = calloc(1, sizeof(*sshc)); + sshc = curlx_calloc(1, sizeof(*sshc)); if(!sshc) return CURLE_OUT_OF_MEMORY; @@ -2557,7 +2547,7 @@ static CURLcode myssh_setup_connection(struct Curl_easy *data, if(Curl_conn_meta_set(conn, CURL_META_SSH_CONN, sshc, myssh_conn_dtor)) return CURLE_OUT_OF_MEMORY; - sshp = calloc(1, sizeof(*sshp)); + sshp = curlx_calloc(1, sizeof(*sshp)); if(!sshp || Curl_meta_set(data, CURL_META_SSH_EASY, sshp, myssh_easy_dtor)) return CURLE_OUT_OF_MEMORY; @@ -2584,10 +2574,7 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done) if(!sshc || !ssh) return CURLE_FAILED_INIT; - /* We default to persistent connections. We set this already in this connect - function to make the reuse checks properly be able to check this bit. */ - connkeep(conn, "SSH default"); - + CURL_TRC_SSH(data, "myssh_connect"); if(conn->handler->protocol & CURLPROTO_SCP) { conn->recv[FIRSTSOCKET] = scp_recv; conn->send[FIRSTSOCKET] = scp_send; @@ -2622,6 +2609,7 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done) /* ignore */ } + CURL_TRC_SSH(data, "myssh_connect, set socket=%" FMT_SOCKET_T, sock); rc = ssh_options_set(sshc->ssh_session, SSH_OPTIONS_FD, &sock); if(rc != SSH_OK) { failf(data, "Could not set socket"); @@ -2695,7 +2683,7 @@ static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done) result = myssh_multi_statemach(data, dophase_done); if(*dophase_done) { - DEBUGF(infof(data, "DO phase is complete")); + CURL_TRC_SSH(data, "DO phase is complete"); } return result; } @@ -2709,14 +2697,13 @@ static CURLcode scp_doing(struct Curl_easy *data, bool *dophase_done) * the options previously setup. */ -static -CURLcode scp_perform(struct Curl_easy *data, - bool *connected, bool *dophase_done) +static CURLcode scp_perform(struct Curl_easy *data, + bool *connected, bool *dophase_done) { CURLcode result = CURLE_OK; struct ssh_conn *sshc = Curl_conn_meta_get(data->conn, CURL_META_SSH_CONN); - DEBUGF(infof(data, "DO phase starts")); + CURL_TRC_SSH(data, "DO phase starts"); *dophase_done = FALSE; /* not done yet */ if(!sshc) @@ -2730,7 +2717,7 @@ CURLcode scp_perform(struct Curl_easy *data, *connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET); if(*dophase_done) { - DEBUGF(infof(data, "DO phase is complete")); + CURL_TRC_SSH(data, "DO phase is complete"); } return result; @@ -2750,13 +2737,10 @@ static CURLcode myssh_do_it(struct Curl_easy *data, bool *done) data->req.size = -1; /* make sure this is unknown at this point */ sshc->actualcode = CURLE_OK; /* reset error code */ - sshc->secondCreateDirs = 0; /* reset the create dir attempt state + sshc->secondCreateDirs = 0; /* reset the create directory attempt state variable */ - Curl_pgrsSetUploadCounter(data, 0); - Curl_pgrsSetDownloadCounter(data, 0); - Curl_pgrsSetUploadSize(data, -1); - Curl_pgrsSetDownloadSize(data, -1); + Curl_pgrsReset(data); if(conn->handler->protocol & CURLPROTO_SCP) result = scp_perform(data, &connected, done); @@ -2834,11 +2818,9 @@ static CURLcode scp_disconnect(struct Curl_easy *data, struct SSHPROTO *sshp = Curl_meta_get(data, CURL_META_SSH_EASY); (void)dead_connection; - if(sshc && sshc->ssh_session && sshp) { + if(sshc && sshc->ssh_session) { /* only if there is a session still around to use! */ - myssh_to(data, sshc, SSH_SESSION_DISCONNECT); - result = myssh_block_statemach(data, sshc, sshp, TRUE); } @@ -2868,7 +2850,6 @@ static CURLcode myssh_done(struct Curl_easy *data, return result; } - static CURLcode scp_done(struct Curl_easy *data, CURLcode status, bool premature) { @@ -2884,7 +2865,7 @@ static CURLcode scp_done(struct Curl_easy *data, CURLcode status, } static CURLcode scp_send(struct Curl_easy *data, int sockindex, - const void *mem, size_t len, bool eos, + const uint8_t *mem, size_t len, bool eos, size_t *pnwritten) { int rc; @@ -2960,15 +2941,14 @@ static CURLcode scp_recv(struct Curl_easy *data, int sockindex, * the options previously setup. */ -static -CURLcode sftp_perform(struct Curl_easy *data, - bool *connected, - bool *dophase_done) +static CURLcode sftp_perform(struct Curl_easy *data, + bool *connected, + bool *dophase_done) { struct ssh_conn *sshc = Curl_conn_meta_get(data->conn, CURL_META_SSH_CONN); CURLcode result = CURLE_OK; - DEBUGF(infof(data, "DO phase starts")); + CURL_TRC_SSH(data, "DO phase starts"); *dophase_done = FALSE; /* not done yet */ if(!sshc) @@ -2983,7 +2963,7 @@ CURLcode sftp_perform(struct Curl_easy *data, *connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET); if(*dophase_done) { - DEBUGF(infof(data, "DO phase is complete")); + CURL_TRC_SSH(data, "DO phase is complete"); } return result; @@ -2995,7 +2975,7 @@ static CURLcode sftp_doing(struct Curl_easy *data, { CURLcode result = myssh_multi_statemach(data, dophase_done); if(*dophase_done) { - DEBUGF(infof(data, "DO phase is complete")); + CURL_TRC_SSH(data, "DO phase is complete"); } return result; } @@ -3012,15 +2992,15 @@ static CURLcode sftp_disconnect(struct Curl_easy *data, CURLcode result = CURLE_OK; (void)dead_connection; - DEBUGF(infof(data, "SSH DISCONNECT starts now")); + CURL_TRC_SSH(data, "DISCONNECT starts now"); - if(sshc && sshc->ssh_session && sshp) { + if(sshc && sshc->ssh_session) { /* only if there is a session still around to use! */ myssh_to(data, sshc, SSH_SFTP_SHUTDOWN); result = myssh_block_statemach(data, sshc, sshp, TRUE); } - DEBUGF(infof(data, "SSH DISCONNECT is done")); + CURL_TRC_SSH(data, "DISCONNECT is done"); return result; } @@ -3045,7 +3025,7 @@ static CURLcode sftp_done(struct Curl_easy *data, CURLcode status, /* return number of sent bytes */ static CURLcode sftp_send(struct Curl_easy *data, int sockindex, - const void *mem, size_t len, bool eos, + const uint8_t *mem, size_t len, bool eos, size_t *pnwritten) { struct connectdata *conn = data->conn; @@ -3061,34 +3041,34 @@ static CURLcode sftp_send(struct Curl_easy *data, int sockindex, #if LIBSSH_VERSION_INT > SSH_VERSION_INT(0, 11, 0) switch(sshc->sftp_send_state) { - case 0: - sftp_file_set_nonblocking(sshc->sftp_file); - if(sftp_aio_begin_write(sshc->sftp_file, mem, len, - &sshc->sftp_send_aio) == SSH_ERROR) { - return CURLE_SEND_ERROR; - } - sshc->sftp_send_state = 1; - FALLTHROUGH(); - case 1: - nwrite = sftp_aio_wait_write(&sshc->sftp_send_aio); - myssh_block2waitfor(conn, sshc, (nwrite == SSH_AGAIN) ? TRUE : FALSE); - if(nwrite == SSH_AGAIN) - return CURLE_AGAIN; - else if(nwrite < 0) - return CURLE_SEND_ERROR; - - /* - * sftp_aio_wait_write() would free sftp_send_aio and - * assign it NULL in all cases except when it returns - * SSH_AGAIN. - */ - - sshc->sftp_send_state = 0; - *pnwritten = (size_t)nwrite; - return CURLE_OK; - default: - /* we never reach here */ + case 0: + sftp_file_set_nonblocking(sshc->sftp_file); + if(sftp_aio_begin_write(sshc->sftp_file, mem, len, + &sshc->sftp_send_aio) == SSH_ERROR) { return CURLE_SEND_ERROR; + } + sshc->sftp_send_state = 1; + FALLTHROUGH(); + case 1: + nwrite = sftp_aio_wait_write(&sshc->sftp_send_aio); + myssh_block2waitfor(conn, sshc, (nwrite == SSH_AGAIN) ? TRUE : FALSE); + if(nwrite == SSH_AGAIN) + return CURLE_AGAIN; + else if(nwrite < 0) + return CURLE_SEND_ERROR; + + /* + * sftp_aio_wait_write() would free sftp_send_aio and + * assign it NULL in all cases except when it returns + * SSH_AGAIN. + */ + + sshc->sftp_send_state = 0; + *pnwritten = (size_t)nwrite; + return CURLE_OK; + default: + /* we never reach here */ + return CURLE_SEND_ERROR; } #else /* @@ -3140,54 +3120,53 @@ static CURLcode sftp_recv(struct Curl_easy *data, int sockindex, return CURLE_FAILED_INIT; switch(sshc->sftp_recv_state) { - case 0: + case 0: #if LIBSSH_VERSION_INT > SSH_VERSION_INT(0, 11, 0) - if(sftp_aio_begin_read(sshc->sftp_file, len, - &sshc->sftp_recv_aio) == SSH_ERROR) { - return CURLE_RECV_ERROR; - } + if(sftp_aio_begin_read(sshc->sftp_file, len, + &sshc->sftp_recv_aio) == SSH_ERROR) { + return CURLE_RECV_ERROR; + } #else - sshc->sftp_file_index = - sftp_async_read_begin(sshc->sftp_file, (uint32_t)len); - if(sshc->sftp_file_index < 0) - return CURLE_RECV_ERROR; + sshc->sftp_file_index = + sftp_async_read_begin(sshc->sftp_file, (uint32_t)len); + if(sshc->sftp_file_index < 0) + return CURLE_RECV_ERROR; #endif - FALLTHROUGH(); - case 1: - sshc->sftp_recv_state = 1; + FALLTHROUGH(); + case 1: + sshc->sftp_recv_state = 1; #if LIBSSH_VERSION_INT > SSH_VERSION_INT(0, 11, 0) - nread = sftp_aio_wait_read(&sshc->sftp_recv_aio, mem, len); + nread = sftp_aio_wait_read(&sshc->sftp_recv_aio, mem, len); #else - nread = sftp_async_read(sshc->sftp_file, mem, (uint32_t)len, - (uint32_t)sshc->sftp_file_index); + nread = sftp_async_read(sshc->sftp_file, mem, (uint32_t)len, + (uint32_t)sshc->sftp_file_index); #endif - myssh_block2waitfor(conn, sshc, (nread == SSH_AGAIN)); + myssh_block2waitfor(conn, sshc, (nread == SSH_AGAIN)); - if(nread == SSH_AGAIN) - return CURLE_AGAIN; - else if(nread < 0) - return CURLE_RECV_ERROR; + if(nread == SSH_AGAIN) + return CURLE_AGAIN; + else if(nread < 0) + return CURLE_RECV_ERROR; - /* - * sftp_aio_wait_read() would free sftp_recv_aio and - * assign it NULL in all cases except when it returns - * SSH_AGAIN. - */ + /* + * sftp_aio_wait_read() would free sftp_recv_aio and + * assign it NULL in all cases except when it returns + * SSH_AGAIN. + */ - sshc->sftp_recv_state = 0; - *pnread = (size_t)nread; - return CURLE_OK; + sshc->sftp_recv_state = 0; + *pnread = (size_t)nread; + return CURLE_OK; - default: - /* we never reach here */ - return CURLE_RECV_ERROR; + default: + /* we never reach here */ + return CURLE_RECV_ERROR; } } - CURLcode Curl_ssh_init(void) { if(ssh_init()) { @@ -3207,4 +3186,4 @@ void Curl_ssh_version(char *buffer, size_t buflen) (void)curl_msnprintf(buffer, buflen, "libssh/%s", ssh_version(0)); } -#endif /* USE_LIBSSH */ +#endif /* USE_LIBSSH */ diff --git a/lib/vssh/libssh2.c b/lib/vssh/libssh2.c index f9160944befe..4d43ddd9f128 100644 --- a/lib/vssh/libssh2.c +++ b/lib/vssh/libssh2.c @@ -28,8 +28,6 @@ #ifdef USE_LIBSSH2 -#include - #ifdef HAVE_NETINET_IN_H #include #endif @@ -44,36 +42,24 @@ #include #endif -#include #include "../urldata.h" #include "../sendf.h" +#include "../curl_trc.h" #include "../hostip.h" #include "../progress.h" #include "../transfer.h" -#include "../escape.h" #include "../http.h" /* for HTTP proxy tunnel stuff */ #include "ssh.h" #include "../url.h" -#include "../speedcheck.h" -#include "../getinfo.h" -#include "../strdup.h" -#include "../vtls/vtls.h" #include "../cfilters.h" #include "../connect.h" #include "../parsedate.h" /* for the week day and month names */ -#include "../sockaddr.h" /* required for Curl_sockaddr_storage */ #include "../multiif.h" #include "../select.h" #include "../curlx/fopen.h" -#include "../curlx/warnless.h" -#include "curl_path.h" +#include "vssh.h" #include "../curlx/strparse.h" #include "../curlx/base64.h" /* for base64 encoding/decoding */ -#include "../curl_sha256.h" - -/* The last 2 #include files should be in this order */ -#include "../curl_memory.h" -#include "../memdebug.h" /* Local functions: */ static const char *sftp_libssh2_strerror(unsigned long err); @@ -128,11 +114,10 @@ const struct Curl_handler Curl_handler_scp = { PORT_SSH, /* defport */ CURLPROTO_SCP, /* protocol */ CURLPROTO_SCP, /* family */ - PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION - | PROTOPT_NOURLQUERY /* flags */ + PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | /* flags */ + PROTOPT_NOURLQUERY | PROTOPT_CONN_REUSE }; - /* * SFTP protocol handler. */ @@ -159,16 +144,16 @@ const struct Curl_handler Curl_handler_sftp = { PORT_SSH, /* defport */ CURLPROTO_SFTP, /* protocol */ CURLPROTO_SFTP, /* family */ - PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION - | PROTOPT_NOURLQUERY /* flags */ + PROTOPT_DIRLOCK | PROTOPT_CLOSEACTION | /* flags */ + PROTOPT_NOURLQUERY | PROTOPT_CONN_REUSE }; -static void -kbd_callback(const char *name, int name_len, const char *instruction, - int instruction_len, int num_prompts, - const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts, - LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses, - void **abstract) +static void kbd_callback(const char *name, int name_len, + const char *instruction, int instruction_len, + int num_prompts, + const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts, + LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses, + void **abstract) { struct Curl_easy *data = (struct Curl_easy *)*abstract; @@ -186,7 +171,7 @@ kbd_callback(const char *name, int name_len, const char *instruction, #endif /* CURL_LIBSSH2_DEBUG */ if(num_prompts == 1) { struct connectdata *conn = data->conn; - responses[0].text = strdup(conn->passwd); + responses[0].text = curlx_strdup(conn->passwd); responses[0].length = responses[0].text == NULL ? 0 : curlx_uztoui(strlen(conn->passwd)); } @@ -196,30 +181,30 @@ kbd_callback(const char *name, int name_len, const char *instruction, static CURLcode sftp_libssh2_error_to_CURLE(unsigned long err) { switch(err) { - case LIBSSH2_FX_OK: - return CURLE_OK; + case LIBSSH2_FX_OK: + return CURLE_OK; - case LIBSSH2_FX_NO_SUCH_FILE: - case LIBSSH2_FX_NO_SUCH_PATH: - return CURLE_REMOTE_FILE_NOT_FOUND; + case LIBSSH2_FX_NO_SUCH_FILE: + case LIBSSH2_FX_NO_SUCH_PATH: + return CURLE_REMOTE_FILE_NOT_FOUND; - case LIBSSH2_FX_PERMISSION_DENIED: - case LIBSSH2_FX_WRITE_PROTECT: - case LIBSSH2_FX_LOCK_CONFlICT: - return CURLE_REMOTE_ACCESS_DENIED; + case LIBSSH2_FX_PERMISSION_DENIED: + case LIBSSH2_FX_WRITE_PROTECT: + case LIBSSH2_FX_LOCK_CONFlICT: + return CURLE_REMOTE_ACCESS_DENIED; - case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM: - case LIBSSH2_FX_QUOTA_EXCEEDED: - return CURLE_REMOTE_DISK_FULL; + case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM: + case LIBSSH2_FX_QUOTA_EXCEEDED: + return CURLE_REMOTE_DISK_FULL; - case LIBSSH2_FX_FILE_ALREADY_EXISTS: - return CURLE_REMOTE_FILE_EXISTS; + case LIBSSH2_FX_FILE_ALREADY_EXISTS: + return CURLE_REMOTE_FILE_EXISTS; - case LIBSSH2_FX_DIR_NOT_EMPTY: - return CURLE_QUOTE_ERROR; + case LIBSSH2_FX_DIR_NOT_EMPTY: + return CURLE_QUOTE_ERROR; - default: - break; + default: + break; } return CURLE_SSH; @@ -228,39 +213,39 @@ static CURLcode sftp_libssh2_error_to_CURLE(unsigned long err) static CURLcode libssh2_session_error_to_CURLE(int err) { switch(err) { - /* Ordered by order of appearance in libssh2.h */ - case LIBSSH2_ERROR_NONE: - return CURLE_OK; + /* Ordered by order of appearance in libssh2.h */ + case LIBSSH2_ERROR_NONE: + return CURLE_OK; - /* This is the error returned by libssh2_scp_recv2 - * on unknown file */ - case LIBSSH2_ERROR_SCP_PROTOCOL: - return CURLE_REMOTE_FILE_NOT_FOUND; + /* This is the error returned by libssh2_scp_recv2 + * on unknown file */ + case LIBSSH2_ERROR_SCP_PROTOCOL: + return CURLE_REMOTE_FILE_NOT_FOUND; - case LIBSSH2_ERROR_SOCKET_NONE: - return CURLE_COULDNT_CONNECT; + case LIBSSH2_ERROR_SOCKET_NONE: + return CURLE_COULDNT_CONNECT; - case LIBSSH2_ERROR_ALLOC: - return CURLE_OUT_OF_MEMORY; + case LIBSSH2_ERROR_ALLOC: + return CURLE_OUT_OF_MEMORY; - case LIBSSH2_ERROR_SOCKET_SEND: - return CURLE_SEND_ERROR; + case LIBSSH2_ERROR_SOCKET_SEND: + return CURLE_SEND_ERROR; - case LIBSSH2_ERROR_HOSTKEY_INIT: - case LIBSSH2_ERROR_HOSTKEY_SIGN: - case LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED: - case LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED: - return CURLE_PEER_FAILED_VERIFICATION; + case LIBSSH2_ERROR_HOSTKEY_INIT: + case LIBSSH2_ERROR_HOSTKEY_SIGN: + case LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED: + case LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED: + return CURLE_PEER_FAILED_VERIFICATION; - case LIBSSH2_ERROR_PASSWORD_EXPIRED: - return CURLE_LOGIN_DENIED; + case LIBSSH2_ERROR_PASSWORD_EXPIRED: + return CURLE_LOGIN_DENIED; - case LIBSSH2_ERROR_SOCKET_TIMEOUT: - case LIBSSH2_ERROR_TIMEOUT: - return CURLE_OPERATION_TIMEDOUT; + case LIBSSH2_ERROR_SOCKET_TIMEOUT: + case LIBSSH2_ERROR_TIMEOUT: + return CURLE_OPERATION_TIMEDOUT; - case LIBSSH2_ERROR_EAGAIN: - return CURLE_AGAIN; + case LIBSSH2_ERROR_EAGAIN: + return CURLE_AGAIN; } return CURLE_SSH; @@ -289,16 +274,9 @@ static LIBSSH2_FREE_FUNC(my_libssh2_free) Curl_cfree(ptr); } -/* - * SSH State machine related code - */ -/* This is the ONLY way to change SSH state! */ -static void myssh_state(struct Curl_easy *data, - struct ssh_conn *sshc, - sshstate nowstate) +#ifndef CURL_DISABLE_VERBOSE_STRINGS +static const char *myssh_statename(sshstate state) { -#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) - /* for debug purposes */ static const char * const names[] = { "SSH_STOP", "SSH_INIT", @@ -361,16 +339,33 @@ static void myssh_state(struct Curl_easy *data, "SSH_SESSION_FREE", "QUIT" }; - /* a precaution to make sure the lists are in sync */ DEBUGASSERT(CURL_ARRAYSIZE(names) == SSH_LAST); + return ((size_t)state < CURL_ARRAYSIZE(names)) ? names[state] : ""; +} +#else +#define myssh_statename(x) "" +#endif /* !CURL_DISABLE_VERBOSE_STRINGS */ + +#define myssh_state(x, y, z) myssh_set_state(x, y, z) +/* + * SSH State machine related code + */ +/* This is the ONLY way to change SSH state! */ +static void myssh_set_state(struct Curl_easy *data, + struct ssh_conn *sshc, + sshstate nowstate) +{ +#ifndef CURL_DISABLE_VERBOSE_STRINGS if(sshc->state != nowstate) { - infof(data, "SFTP %p state change from %s to %s", - (void *)sshc, names[sshc->state], names[nowstate]); + CURL_TRC_SSH(data, "[%s] -> [%s]", + myssh_statename(sshc->state), + myssh_statename(nowstate)); } -#endif +#else (void)data; +#endif sshc->state = nowstate; } @@ -607,7 +602,7 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data, /* The length of fingerprint is 32 bytes for SHA256. * See libssh2_hostkey_hash documentation. */ - if(curlx_base64_encode(fingerprint, 32, &fingerprint_b64, + if(curlx_base64_encode((const uint8_t *)fingerprint, 32, &fingerprint_b64, &fingerprint_b64_len) != CURLE_OK) { myssh_state(data, sshc, SSH_SESSION_FREE); return CURLE_PEER_FAILED_VERIFICATION; @@ -640,12 +635,12 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data, failf(data, "Denied establishing ssh session: mismatch sha256 fingerprint. " "Remote %s is not equal to %s", fingerprint_b64, pubkey_sha256); - free(fingerprint_b64); + curlx_free(fingerprint_b64); myssh_state(data, sshc, SSH_SESSION_FREE); return CURLE_PEER_FAILED_VERIFICATION; } - free(fingerprint_b64); + curlx_free(fingerprint_b64); infof(data, "SHA256 checksum match"); } @@ -661,7 +656,7 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data, /* The fingerprint points to static storage (!), do not free() it. */ int i; for(i = 0; i < 16; i++) { - curl_msnprintf(&md5buffer[i*2], 3, "%02x", + curl_msnprintf(&md5buffer[i * 2], 3, "%02x", (unsigned char)fingerprint[i]); } @@ -701,7 +696,7 @@ static CURLcode ssh_check_fingerprint(struct Curl_easy *data, rc = data->set.ssh_hostkeyfunc(data->set.ssh_hostkeyfunc_userp, (int)keytype, remotekey, keylen); Curl_set_in_callback(data, FALSE); - if(rc!= CURLKHMATCH_OK) { + if(rc != CURLKHMATCH_OK) { myssh_state(data, sshc, SSH_SESSION_FREE); return CURLE_PEER_FAILED_VERIFICATION; } @@ -731,30 +726,20 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data, { CURLcode result = CURLE_OK; - static const char * const hostkey_method_ssh_ed25519 - = "ssh-ed25519"; - static const char * const hostkey_method_ssh_ecdsa_521 - = "ecdsa-sha2-nistp521"; - static const char * const hostkey_method_ssh_ecdsa_384 - = "ecdsa-sha2-nistp384"; - static const char * const hostkey_method_ssh_ecdsa_256 - = "ecdsa-sha2-nistp256"; - static const char * const hostkey_method_ssh_rsa_all - = "rsa-sha2-256,rsa-sha2-512,ssh-rsa"; - static const char * const hostkey_method_ssh_dss - = "ssh-dss"; - - const char *hostkey_method = NULL; - struct connectdata *conn = data->conn; - struct libssh2_knownhost* store = NULL; - const char *kh_name_end = NULL; - size_t kh_name_size = 0; - int port = 0; + static const char hostkey_method_ssh_ed25519[] = "ssh-ed25519"; + static const char hostkey_method_ssh_ecdsa_521[] = "ecdsa-sha2-nistp521"; + static const char hostkey_method_ssh_ecdsa_384[] = "ecdsa-sha2-nistp384"; + static const char hostkey_method_ssh_ecdsa_256[] = "ecdsa-sha2-nistp256"; + static const char hostkey_method_ssh_rsa_all[] = + "rsa-sha2-256,rsa-sha2-512,ssh-rsa"; + static const char hostkey_method_ssh_dss[] = "ssh-dss"; bool found = FALSE; if(sshc->kh && !data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5] && !data->set.str[STRING_SSH_HOST_PUBLIC_KEY_SHA256]) { + struct libssh2_knownhost *store = NULL; + struct connectdata *conn = data->conn; /* lets try to find our host in the known hosts file */ while(!libssh2_knownhost_get(sshc->kh, &store, store)) { /* For non-standard ports, the name will be enclosed in */ @@ -762,17 +747,21 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data, if(store) { if(store->name) { if(store->name[0] == '[') { - kh_name_end = strstr(store->name, "]:"); + curl_off_t port; + size_t kh_name_size = 0; + const char *p; + const char *kh_name_end = strstr(store->name, "]:"); if(!kh_name_end) { infof(data, "Invalid host pattern %s in %s", store->name, data->set.str[STRING_SSH_KNOWNHOSTS]); continue; } - port = atoi(kh_name_end + 2); - if(kh_name_end && (port == conn->remote_port)) { + p = kh_name_end + 2; /* start of port number */ + if(!curlx_str_number(&p, &port, 0xffff) && + (kh_name_end && (port == conn->remote_port))) { kh_name_size = strlen(store->name) - 1 - strlen(kh_name_end); if(strncmp(store->name + 1, - conn->host.name, kh_name_size) == 0) { + conn->host.name, kh_name_size) == 0) { found = TRUE; break; } @@ -792,6 +781,7 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data, if(found) { int rc; + const char *hostkey_method = NULL; infof(data, "Found host %s in %s", conn->host.name, data->set.str[STRING_SSH_KNOWNHOSTS]); @@ -830,7 +820,7 @@ static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data, char *errmsg = NULL; int errlen; libssh2_session_last_error(sshc->ssh_session, &errmsg, &errlen, 0); - failf(data, "libssh2: %s", errmsg); + failf(data, "libssh2 method '%s' failed: %s", hostkey_method, errmsg); result = libssh2_session_error_to_CURLE(rc); } } @@ -887,11 +877,11 @@ static CURLcode sftp_quote(struct Curl_easy *data, Curl_debug(data, CURLINFO_HEADER_OUT, "PWD\n", 4); Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp)); - /* this sends an FTP-like "header" to the header callback so that the - current directory can be read very similar to how it is read when + /* this sends an FTP-like "header" to the header callback so that + the current directory can be read similar to how it is read when using ordinary FTP. */ result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp)); - free(tmp); + curlx_free(tmp); if(!result) myssh_state(data, sshc, SSH_SFTP_NEXT_QUOTE); return result; @@ -966,7 +956,7 @@ static CURLcode sftp_quote(struct Curl_easy *data, else if(!strncmp(cmd, "mkdir ", 6)) { if(*cp) return_quote_error(data, sshc); - /* create dir */ + /* create directory */ myssh_state(data, sshc, SSH_SFTP_QUOTE_MKDIR); return result; } @@ -989,7 +979,7 @@ static CURLcode sftp_quote(struct Curl_easy *data, else if(!strncmp(cmd, "rmdir ", 6)) { if(*cp) return_quote_error(data, sshc); - /* delete dir */ + /* delete directory */ myssh_state(data, sshc, SSH_SFTP_QUOTE_RMDIR); return result; } @@ -1012,11 +1002,10 @@ static CURLcode sftp_quote(struct Curl_easy *data, return CURLE_QUOTE_ERROR; } -static CURLcode -sftp_upload_init(struct Curl_easy *data, - struct ssh_conn *sshc, - struct SSHPROTO *sshp, - bool *blockp) +static CURLcode sftp_upload_init(struct Curl_easy *data, + struct ssh_conn *sshc, + struct SSHPROTO *sshp, + bool *blockp) { unsigned long flags; @@ -1143,7 +1132,7 @@ sftp_upload_init(struct Curl_easy *data, } /* seekerr == CURL_SEEKFUNC_CANTSEEK (cannot seek to offset) */ do { - char scratch[4*1024]; + char scratch[4 * 1024]; size_t readthisamountnow = (data->state.resume_from - passed > (curl_off_t)sizeof(scratch)) ? @@ -1186,10 +1175,6 @@ sftp_upload_init(struct Curl_easy *data, /* not set by Curl_xfer_setup to preserve keepon bits */ data->conn->recv_idx = FIRSTSOCKET; - /* store this original bitmask setup to use later on if we cannot - figure out a "real" bitmask */ - sshc->orig_waitfor = data->req.keepon; - /* since we do not really wait for anything at this point, we want the state machine to move on as soon as possible so mark this as dirty */ Curl_multi_mark_dirty(data); @@ -1213,8 +1198,11 @@ static CURLcode ssh_state_pkey_init(struct Curl_easy *data, sshc->rsa_pub = sshc->rsa = NULL; - if(data->set.str[STRING_SSH_PRIVATE_KEY]) - sshc->rsa = strdup(data->set.str[STRING_SSH_PRIVATE_KEY]); + if(data->set.str[STRING_SSH_PRIVATE_KEY]) { + sshc->rsa = curlx_strdup(data->set.str[STRING_SSH_PRIVATE_KEY]); + if(!sshc->rsa) + out_of_memory = TRUE; + } else { /* To ponder about: should really the lib be messing about with the HOME environment variable etc? */ @@ -1228,7 +1216,7 @@ static CURLcode ssh_state_pkey_init(struct Curl_easy *data, if(!sshc->rsa) out_of_memory = TRUE; else if(curlx_stat(sshc->rsa, &sbuf)) { - free(sshc->rsa); + curlx_free(sshc->rsa); sshc->rsa = curl_maprintf("%s/.ssh/id_dsa", home); if(!sshc->rsa) out_of_memory = TRUE; @@ -1236,19 +1224,19 @@ static CURLcode ssh_state_pkey_init(struct Curl_easy *data, Curl_safefree(sshc->rsa); } } - free(home); + curlx_free(home); } if(!out_of_memory && !sshc->rsa) { /* Nothing found; try the current dir. */ - sshc->rsa = strdup("id_rsa"); + sshc->rsa = curlx_strdup("id_rsa"); if(sshc->rsa && curlx_stat(sshc->rsa, &sbuf)) { - free(sshc->rsa); - sshc->rsa = strdup("id_dsa"); + curlx_free(sshc->rsa); + sshc->rsa = curlx_strdup("id_dsa"); if(sshc->rsa && curlx_stat(sshc->rsa, &sbuf)) { - free(sshc->rsa); + curlx_free(sshc->rsa); /* Out of guesses. Set to the empty string to avoid * surprising info messages. */ - sshc->rsa = strdup(""); + sshc->rsa = curlx_strdup(""); } } } @@ -1259,10 +1247,10 @@ static CURLcode ssh_state_pkey_init(struct Curl_easy *data, * libssh2 extract the public key from the private key file. * This is done by simply passing sshc->rsa_pub = NULL. */ - if(data->set.str[STRING_SSH_PUBLIC_KEY] + if(!out_of_memory && data->set.str[STRING_SSH_PUBLIC_KEY] /* treat empty string the same way as NULL */ && data->set.str[STRING_SSH_PUBLIC_KEY][0]) { - sshc->rsa_pub = strdup(data->set.str[STRING_SSH_PUBLIC_KEY]); + sshc->rsa_pub = curlx_strdup(data->set.str[STRING_SSH_PUBLIC_KEY]); if(!sshc->rsa_pub) out_of_memory = TRUE; } @@ -1290,11 +1278,10 @@ static CURLcode ssh_state_pkey_init(struct Curl_easy *data, return 0; } -static CURLcode -sftp_quote_stat(struct Curl_easy *data, - struct ssh_conn *sshc, - struct SSHPROTO *sshp, - bool *blockp) +static CURLcode sftp_quote_stat(struct Curl_easy *data, + struct ssh_conn *sshc, + struct SSHPROTO *sshp, + bool *blockp) { char *cmd = sshc->quote_item->data; sshc->acceptfail = FALSE; @@ -1402,11 +1389,10 @@ sftp_quote_stat(struct Curl_easy *data, return CURLE_QUOTE_ERROR; } -static CURLcode -sftp_download_stat(struct Curl_easy *data, - struct ssh_conn *sshc, - struct SSHPROTO *sshp, - bool *blockp) +static CURLcode sftp_download_stat(struct Curl_easy *data, + struct ssh_conn *sshc, + struct SSHPROTO *sshp, + bool *blockp) { LIBSSH2_SFTP_ATTRIBUTES attrs; int rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path, @@ -1438,42 +1424,11 @@ sftp_download_stat(struct Curl_easy *data, return CURLE_BAD_DOWNLOAD_RESUME; } if(data->state.use_range) { - curl_off_t from, to; - const char *p = data->state.range; - int to_t, from_t; - - from_t = curlx_str_number(&p, &from, CURL_OFF_T_MAX); - if(from_t == STRE_OVERFLOW) - return CURLE_RANGE_ERROR; - curlx_str_passblanks(&p); - (void)curlx_str_single(&p, '-'); - - to_t = curlx_str_numblanks(&p, &to); - if(to_t == STRE_OVERFLOW) - return CURLE_RANGE_ERROR; - if((to_t == STRE_NO_NUM) /* no "to" value given */ - || (to >= size)) { - to = size - 1; - } - if(from_t) { - /* from is relative to end of file */ - from = size - to; - to = size - 1; - } - if(from > size) { - failf(data, "Offset (%" FMT_OFF_T ") was beyond file size (%" - FMT_OFF_T ")", from, (curl_off_t)attrs.filesize); - return CURLE_BAD_DOWNLOAD_RESUME; - } - if(from > to) { - from = to; - size = 0; - } - else { - if((to - from) == CURL_OFF_T_MAX) - return CURLE_RANGE_ERROR; - size = to - from + 1; - } + curl_off_t from; + CURLcode result = Curl_ssh_range(data, data->state.range, size, + &from, &size); + if(result) + return result; libssh2_sftp_seek64(sshc->sftp_handle, (libssh2_uint64_t)from); } @@ -1506,8 +1461,7 @@ sftp_download_stat(struct Curl_easy *data, /* Now store the number of bytes we are expected to download */ data->req.size = attrs.filesize - data->state.resume_from; data->req.maxdownload = attrs.filesize - data->state.resume_from; - Curl_pgrsSetDownloadSize(data, - attrs.filesize - data->state.resume_from); + Curl_pgrsSetDownloadSize(data, attrs.filesize - data->state.resume_from); libssh2_sftp_seek64(sshc->sftp_handle, (libssh2_uint64_t)data->state.resume_from); } @@ -1545,7 +1499,7 @@ static CURLcode sftp_readdir(struct Curl_easy *data, return result; } if(rc > 0) { - size_t readdir_len = (size_t) rc; + size_t readdir_len = (size_t)rc; sshp->readdir_filename[readdir_len] = '\0'; if(data->set.list_only) { @@ -1677,8 +1631,7 @@ static CURLcode ssh_state_authlist(struct Curl_easy *data, myssh_state(data, sshc, SSH_SESSION_FREE); return libssh2_session_error_to_CURLE(rc); } - infof(data, "SSH authentication methods available: %s", - sshc->authlist); + infof(data, "SSH authentication methods available: %s", sshc->authlist); myssh_state(data, sshc, SSH_AUTH_PKEY_INIT); return CURLE_OK; @@ -1717,8 +1670,7 @@ static CURLcode ssh_state_auth_pkey(struct Curl_easy *data, err_msg = unknown; } else { - (void)libssh2_session_last_error(sshc->ssh_session, - &err_msg, NULL, 0); + (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); } infof(data, "SSH public key authentication failed: %s", err_msg); myssh_state(data, sshc, SSH_AUTH_PASS_INIT); @@ -1780,8 +1732,8 @@ static CURLcode ssh_state_auth_agent_init(struct Curl_easy *data, struct ssh_conn *sshc) { int rc = 0; - if((data->set.ssh_auth_types & CURLSSH_AUTH_AGENT) - && (strstr(sshc->authlist, "publickey") != NULL)) { + if((data->set.ssh_auth_types & CURLSSH_AUTH_AGENT) && + (strstr(sshc->authlist, "publickey") != NULL)) { /* Connect to the ssh-agent */ /* The agent could be shared by a curl thread i believe @@ -1876,8 +1828,8 @@ static CURLcode ssh_state_auth_agent(struct Curl_easy *data, static CURLcode ssh_state_auth_key_init(struct Curl_easy *data, struct ssh_conn *sshc) { - if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) - && (strstr(sshc->authlist, "keyboard-interactive") != NULL)) { + if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) && + (strstr(sshc->authlist, "keyboard-interactive") != NULL)) { myssh_state(data, sshc, SSH_AUTH_KEY); } else { @@ -1951,8 +1903,7 @@ static CURLcode ssh_state_sftp_init(struct Curl_easy *data, LIBSSH2_ERROR_EAGAIN) return CURLE_AGAIN; - (void)libssh2_session_last_error(sshc->ssh_session, - &err_msg, NULL, 0); + (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); failf(data, "Failure initializing sftp session: %s", err_msg); myssh_state(data, sshc, SSH_SESSION_FREE); return CURLE_FAILED_INIT; @@ -1977,12 +1928,12 @@ static CURLcode ssh_state_sftp_realpath(struct Curl_easy *data, myssh_state(data, sshc, SSH_STOP); if(rc > 0) { - free(sshc->homedir); - sshc->homedir = strdup(sshp->readdir_filename); + curlx_free(sshc->homedir); + sshc->homedir = curlx_strdup(sshp->readdir_filename); if(!sshc->homedir) return CURLE_OUT_OF_MEMORY; - free(data->state.most_recent_ftp_entrypath); - data->state.most_recent_ftp_entrypath = strdup(sshc->homedir); + curlx_free(data->state.most_recent_ftp_entrypath); + data->state.most_recent_ftp_entrypath = curlx_strdup(sshc->homedir); if(!data->state.most_recent_ftp_entrypath) return CURLE_OUT_OF_MEMORY; } @@ -1996,8 +1947,7 @@ static CURLcode ssh_state_sftp_realpath(struct Curl_easy *data, /* in this case, the error was not in the SFTP level but for example a time-out or similar */ result = CURLE_SSH; - DEBUGF(infof(data, "error = %lu makes libcurl = %d", - sftperr, (int)result)); + CURL_TRC_SSH(data, "error = %lu makes libcurl = %d", sftperr, (int)result); return result; } @@ -2005,7 +1955,7 @@ static CURLcode ssh_state_sftp_realpath(struct Curl_easy *data, get the homedir here, we get the "workingpath" in the DO action since the homedir will remain the same between request but the working path will not. */ - DEBUGF(infof(data, "SSH CONNECT phase done")); + CURL_TRC_SSH(data, "CONNECT phase done"); return CURLE_OK; } @@ -2107,10 +2057,10 @@ static CURLcode ssh_state_sftp_quote_setstat(struct Curl_easy *data, if(rc && !sshc->acceptfail) { unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session); + failf(data, "Attempt to set SFTP stats for \"%s\" failed: %s", + sshc->quote_path2, sftp_libssh2_strerror(sftperr)); Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); - failf(data, "Attempt to set SFTP stats failed: %s", - sftp_libssh2_strerror(sftperr)); myssh_state(data, sshc, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; return CURLE_QUOTE_ERROR; @@ -2133,10 +2083,11 @@ static CURLcode ssh_state_sftp_quote_symlink(struct Curl_easy *data, if(rc && !sshc->acceptfail) { unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session); + failf(data, "symlink \"%s\" to \"%s\" failed: %s", + sshc->quote_path1, sshc->quote_path2, + sftp_libssh2_strerror(sftperr)); Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); - failf(data, "symlink command failed: %s", - sftp_libssh2_strerror(sftperr)); myssh_state(data, sshc, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; return CURLE_QUOTE_ERROR; @@ -2156,9 +2107,9 @@ static CURLcode ssh_state_sftp_quote_mkdir(struct Curl_easy *data, if(rc && !sshc->acceptfail) { unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session); + failf(data, "mkdir \"%s\" failed: %s", + sshc->quote_path1, sftp_libssh2_strerror(sftperr)); Curl_safefree(sshc->quote_path1); - failf(data, "mkdir command failed: %s", - sftp_libssh2_strerror(sftperr)); myssh_state(data, sshc, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; return CURLE_QUOTE_ERROR; @@ -2184,10 +2135,11 @@ static CURLcode ssh_state_sftp_quote_rename(struct Curl_easy *data, if(rc && !sshc->acceptfail) { unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session); + failf(data, "rename \"%s\" to \"%s\" failed: %s", + sshc->quote_path1, sshc->quote_path2, + sftp_libssh2_strerror(sftperr)); Curl_safefree(sshc->quote_path1); Curl_safefree(sshc->quote_path2); - failf(data, "rename command failed: %s", - sftp_libssh2_strerror(sftperr)); myssh_state(data, sshc, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; return CURLE_QUOTE_ERROR; @@ -2206,9 +2158,9 @@ static CURLcode ssh_state_sftp_quote_rmdir(struct Curl_easy *data, if(rc && !sshc->acceptfail) { unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session); + failf(data, "rmdir \"%s\" failed: %s", + sshc->quote_path1, sftp_libssh2_strerror(sftperr)); Curl_safefree(sshc->quote_path1); - failf(data, "rmdir command failed: %s", - sftp_libssh2_strerror(sftperr)); myssh_state(data, sshc, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; return CURLE_QUOTE_ERROR; @@ -2227,8 +2179,9 @@ static CURLcode ssh_state_sftp_quote_unlink(struct Curl_easy *data, if(rc && !sshc->acceptfail) { unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session); + failf(data, "rm \"%s\" failed: %s", + sshc->quote_path1, sftp_libssh2_strerror(sftperr)); Curl_safefree(sshc->quote_path1); - failf(data, "rm command failed: %s", sftp_libssh2_strerror(sftperr)); myssh_state(data, sshc, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; return CURLE_QUOTE_ERROR; @@ -2250,9 +2203,9 @@ static CURLcode ssh_state_sftp_quote_statvfs(struct Curl_easy *data, if(rc && !sshc->acceptfail) { unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session); + failf(data, "statvfs \"%s\" failed: %s", + sshc->quote_path1, sftp_libssh2_strerror(sftperr)); Curl_safefree(sshc->quote_path1); - failf(data, "statvfs command failed: %s", - sftp_libssh2_strerror(sftperr)); myssh_state(data, sshc, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; return CURLE_QUOTE_ERROR; @@ -2289,7 +2242,7 @@ static CURLcode ssh_state_sftp_quote_statvfs(struct Curl_easy *data, } result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp)); - free(tmp); + curlx_free(tmp); if(result) { myssh_state(data, sshc, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; @@ -2315,9 +2268,9 @@ static CURLcode ssh_state_sftp_create_dirs_mkdir(struct Curl_easy *data, ++sshc->slash_pos; if(rc < 0) { /* - * Abort if failure was not that the dir already exists or the - * permission was denied (creation might succeed further down the - * path) - retry on unspecific FAILURE also + * Abort if failure was not that the directory already exists or + * the permission was denied (creation might succeed further down + * the path) - retry on unspecific FAILURE also */ unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session); if((sftperr != LIBSSH2_FX_FILE_ALREADY_EXISTS) && @@ -2420,8 +2373,7 @@ static CURLcode ssh_state_scp_download_init(struct Curl_easy *data, LIBSSH2_ERROR_EAGAIN) return CURLE_AGAIN; - ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session, - &err_msg, NULL, 0)); + ssh_err = libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); failf(data, "%s", err_msg); myssh_state(data, sshc, SSH_SCP_CHANNEL_FREE); return libssh2_session_error_to_CURLE(ssh_err); @@ -2451,8 +2403,7 @@ static CURLcode ssh_state_sftp_close(struct Curl_easy *data, if(rc < 0) { char *err_msg = NULL; - (void)libssh2_session_last_error(sshc->ssh_session, - &err_msg, NULL, 0); + (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg); } sshc->sftp_handle = NULL; @@ -2460,7 +2411,7 @@ static CURLcode ssh_state_sftp_close(struct Curl_easy *data, Curl_safefree(sshp->path); - DEBUGF(infof(data, "SFTP DONE done")); + CURL_TRC_SSH(data, "SFTP DONE done"); /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT After nextstate is executed, the control should come back to @@ -2490,8 +2441,7 @@ static CURLcode ssh_state_sftp_shutdown(struct Curl_easy *data, if(rc < 0) { char *err_msg = NULL; - (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, - NULL, 0); + (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg); } sshc->sftp_handle = NULL; @@ -2563,8 +2513,7 @@ static CURLcode ssh_state_scp_upload_init(struct Curl_easy *data, LIBSSH2_ERROR_EAGAIN) return CURLE_AGAIN; - ssh_err = (int)(libssh2_session_last_error(sshc->ssh_session, - &err_msg, NULL, 0)); + ssh_err = libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); failf(data, "%s", err_msg); myssh_state(data, sshc, SSH_SCP_CHANNEL_FREE); result = libssh2_session_error_to_CURLE(ssh_err); @@ -2584,10 +2533,6 @@ static CURLcode ssh_state_scp_upload_init(struct Curl_easy *data, /* not set by Curl_xfer_setup to preserve keepon bits */ data->conn->recv_idx = FIRSTSOCKET; - /* store this original bitmask setup to use later on if we cannot - figure out a "real" bitmask */ - sshc->orig_waitfor = data->req.keepon; - myssh_state(data, sshc, SSH_STOP); return CURLE_OK; @@ -2607,10 +2552,8 @@ static CURLcode ssh_state_session_disconnect(struct Curl_easy *data, if(rc < 0) { char *err_msg = NULL; - (void)libssh2_session_last_error(sshc->ssh_session, - &err_msg, NULL, 0); - infof(data, "Failed to free libssh2 scp subsystem: %d %s", - rc, err_msg); + (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); + infof(data, "Failed to free libssh2 scp subsystem: %d %s", rc, err_msg); } sshc->ssh_channel = NULL; } @@ -2622,10 +2565,8 @@ static CURLcode ssh_state_session_disconnect(struct Curl_easy *data, if(rc < 0) { char *err_msg = NULL; - (void)libssh2_session_last_error(sshc->ssh_session, - &err_msg, NULL, 0); - infof(data, "Failed to disconnect libssh2 session: %d %s", - rc, err_msg); + (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); + infof(data, "Failed to disconnect libssh2 session: %d %s", rc, err_msg); } } @@ -2725,11 +2666,13 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, break; case SSH_SFTP_REALPATH: - result = ssh_state_sftp_realpath(data, sshc, sshp); + result = sshp ? ssh_state_sftp_realpath(data, sshc, sshp) : + CURLE_FAILED_INIT; break; case SSH_SFTP_QUOTE_INIT: - result = ssh_state_sftp_quote_init(data, sshc, sshp); + result = sshp ? ssh_state_sftp_quote_init(data, sshc, sshp) : + CURLE_FAILED_INIT; break; case SSH_SFTP_POSTQUOTE_INIT: @@ -2737,7 +2680,8 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, break; case SSH_SFTP_QUOTE: - result = ssh_state_sftp_quote(data, sshc, sshp); + result = sshp ? ssh_state_sftp_quote(data, sshc, sshp) : + CURLE_FAILED_INIT; break; case SSH_SFTP_NEXT_QUOTE: @@ -2745,11 +2689,13 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, break; case SSH_SFTP_QUOTE_STAT: - result = ssh_state_sftp_quote_stat(data, sshc, sshp, block); + result = sshp ? ssh_state_sftp_quote_stat(data, sshc, sshp, block) : + CURLE_FAILED_INIT; break; case SSH_SFTP_QUOTE_SETSTAT: - result = ssh_state_sftp_quote_setstat(data, sshc, sshp); + result = sshp ? ssh_state_sftp_quote_setstat(data, sshc, sshp) : + CURLE_FAILED_INIT; break; case SSH_SFTP_QUOTE_SYMLINK: @@ -2785,13 +2731,17 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, } break; - case SSH_SFTP_FILETIME: - { + case SSH_SFTP_FILETIME: { LIBSSH2_SFTP_ATTRIBUTES attrs; + int rc; - int rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path, - curlx_uztoui(strlen(sshp->path)), - LIBSSH2_SFTP_STAT, &attrs); + if(!sshp) { + result = CURLE_FAILED_INIT; + break; + } + rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path, + curlx_uztoui(strlen(sshp->path)), + LIBSSH2_SFTP_STAT, &attrs); if(rc == LIBSSH2_ERROR_EAGAIN) { result = CURLE_AGAIN; break; @@ -2807,16 +2757,19 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, case SSH_SFTP_TRANS_INIT: if(data->state.upload) myssh_state(data, sshc, SSH_SFTP_UPLOAD_INIT); - else { - if(sshp->path[strlen(sshp->path)-1] == '/') + else if(sshp) { + if(sshp->path[strlen(sshp->path) - 1] == '/') myssh_state(data, sshc, SSH_SFTP_READDIR_INIT); else myssh_state(data, sshc, SSH_SFTP_DOWNLOAD_INIT); } + else + result = CURLE_FAILED_INIT; break; case SSH_SFTP_UPLOAD_INIT: - result = sftp_upload_init(data, sshc, sshp, block); + result = sshp ? sftp_upload_init(data, sshc, sshp, block) : + CURLE_FAILED_INIT; if(result) { myssh_state(data, sshc, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; @@ -2824,7 +2777,9 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, break; case SSH_SFTP_CREATE_DIRS_INIT: - if(strlen(sshp->path) > 1) { + if(!sshp) + result = CURLE_FAILED_INIT; + else if(strlen(sshp->path) > 1) { sshc->slash_pos = sshp->path + 1; /* ignore the leading '/' */ myssh_state(data, sshc, SSH_SFTP_CREATE_DIRS); } @@ -2834,6 +2789,10 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, break; case SSH_SFTP_CREATE_DIRS: + if(!sshp) { + result = CURLE_FAILED_INIT; + break; + } sshc->slash_pos = strchr(sshc->slash_pos, '/'); if(sshc->slash_pos) { *sshc->slash_pos = 0; @@ -2846,25 +2805,33 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, break; case SSH_SFTP_CREATE_DIRS_MKDIR: - result = ssh_state_sftp_create_dirs_mkdir(data, sshc, sshp); + result = sshp ? ssh_state_sftp_create_dirs_mkdir(data, sshc, sshp) : + CURLE_FAILED_INIT; break; case SSH_SFTP_READDIR_INIT: - result = ssh_state_sftp_readdir_init(data, sshc, sshp); + result = sshp ? ssh_state_sftp_readdir_init(data, sshc, sshp) : + CURLE_FAILED_INIT; break; case SSH_SFTP_READDIR: - result = sftp_readdir(data, sshc, sshp, block); + result = sshp ? sftp_readdir(data, sshc, sshp, block) : + CURLE_FAILED_INIT; if(result) { myssh_state(data, sshc, SSH_SFTP_CLOSE); } break; case SSH_SFTP_READDIR_LINK: - result = ssh_state_sftp_readdir_link(data, sshc, sshp); + result = sshp ? ssh_state_sftp_readdir_link(data, sshc, sshp) : + CURLE_FAILED_INIT; break; case SSH_SFTP_READDIR_BOTTOM: + if(!sshp) { + result = CURLE_FAILED_INIT; + break; + } result = curlx_dyn_addn(&sshp->readdir, "\n", 1); if(!result) result = Curl_client_write(data, CLIENTWRITE_BODY, @@ -2894,11 +2861,13 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, break; case SSH_SFTP_DOWNLOAD_INIT: - result = ssh_state_sftp_download_init(data, sshc, sshp); + result = sshp ? ssh_state_sftp_download_init(data, sshc, sshp) : + CURLE_FAILED_INIT; break; case SSH_SFTP_DOWNLOAD_STAT: - result = sftp_download_stat(data, sshc, sshp, block); + result = sshp ? sftp_download_stat(data, sshc, sshp, block) : + CURLE_FAILED_INIT; if(result) { myssh_state(data, sshc, SSH_SFTP_CLOSE); sshc->nextstate = SSH_NO_STATE; @@ -2906,7 +2875,8 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, break; case SSH_SFTP_CLOSE: - result = ssh_state_sftp_close(data, sshc, sshp); + result = sshp ? ssh_state_sftp_close(data, sshc, sshp) : + CURLE_FAILED_INIT; break; case SSH_SFTP_SHUTDOWN: @@ -2914,7 +2884,8 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, break; case SSH_SCP_TRANS_INIT: - result = Curl_getworkingpath(data, sshc->homedir, &sshp->path); + result = sshp ? Curl_getworkingpath(data, sshc->homedir, &sshp->path) : + CURLE_FAILED_INIT; if(result) { myssh_state(data, sshc, SSH_STOP); break; @@ -2935,11 +2906,13 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, break; case SSH_SCP_UPLOAD_INIT: - result = ssh_state_scp_upload_init(data, sshc, sshp); + result = sshp ? ssh_state_scp_upload_init(data, sshc, sshp) : + CURLE_FAILED_INIT; break; case SSH_SCP_DOWNLOAD_INIT: - result = ssh_state_scp_download_init(data, sshc, sshp); + result = sshp ? ssh_state_scp_download_init(data, sshc, sshp) : + CURLE_FAILED_INIT; break; case SSH_SCP_DONE: @@ -3017,7 +2990,7 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, } sshc->ssh_channel = NULL; } - DEBUGF(infof(data, "SCP DONE phase complete")); + CURL_TRC_SSH(data, "SCP DONE phase complete"); myssh_state(data, sshc, SSH_STOP); break; @@ -3051,6 +3024,8 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, *block = TRUE; result = CURLE_OK; } + CURL_TRC_SSH(data, "[%s] statemachine() -> %d, block=%d", + myssh_statename(sshc->state), result, *block); return result; } @@ -3060,15 +3035,29 @@ static CURLcode ssh_statemachine(struct Curl_easy *data, static CURLcode ssh_pollset(struct Curl_easy *data, struct easy_pollset *ps) { - int flags = 0; struct connectdata *conn = data->conn; - if(conn->waitfor & KEEP_RECV) - flags |= CURL_POLL_IN; - if(conn->waitfor & KEEP_SEND) - flags |= CURL_POLL_OUT; - return flags ? - Curl_pollset_change(data, ps, conn->sock[FIRSTSOCKET], flags, 0) : - CURLE_OK; + struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN); + curl_socket_t sock = conn->sock[FIRSTSOCKET]; + int waitfor; + + if(!sshc || (sock == CURL_SOCKET_BAD)) + return CURLE_FAILED_INIT; + + waitfor = sshc->waitfor ? sshc->waitfor : data->req.keepon; + if(waitfor) { + int flags = 0; + if(waitfor & KEEP_RECV) + flags |= CURL_POLL_IN; + if(waitfor & KEEP_SEND) + flags |= CURL_POLL_OUT; + DEBUGASSERT(flags); + CURL_TRC_SSH(data, "pollset, flags=%x", flags); + return Curl_pollset_change(data, ps, sock, flags, 0); + } + /* While we still have a session, we listen incoming data. */ + if(sshc->ssh_session) + return Curl_pollset_change(data, ps, sock, CURL_POLL_IN, 0); + return CURLE_OK; } /* @@ -3082,20 +3071,18 @@ static void ssh_block2waitfor(struct Curl_easy *data, struct ssh_conn *sshc, bool block) { - struct connectdata *conn = data->conn; int dir = 0; + (void)data; if(block) { dir = libssh2_session_block_directions(sshc->ssh_session); if(dir) { /* translate the libssh2 define bits into our own bit defines */ - conn->waitfor = ((dir&LIBSSH2_SESSION_BLOCK_INBOUND) ? KEEP_RECV : 0) | - ((dir&LIBSSH2_SESSION_BLOCK_OUTBOUND) ? KEEP_SEND : 0); + sshc->waitfor = ((dir & LIBSSH2_SESSION_BLOCK_INBOUND) ? KEEP_RECV : 0) | + ((dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) ? KEEP_SEND : 0); } } if(!dir) - /* It did not block or libssh2 did not reveal in which direction, put back - the original set */ - conn->waitfor = sshc->orig_waitfor; + sshc->waitfor = 0; } /* called repeatedly until done from multi.c */ @@ -3127,32 +3114,28 @@ static CURLcode ssh_block_statemach(struct Curl_easy *data, bool disconnect) { CURLcode result = CURLE_OK; - struct curltime dis = curlx_now(); + struct curltime start = *Curl_pgrs_now(data); while((sshc->state != SSH_STOP) && !result) { bool block; - timediff_t left = 1000; - struct curltime now = curlx_now(); + timediff_t left_ms = 1000; result = ssh_statemachine(data, sshc, sshp, &block); if(result) break; if(!disconnect) { - if(Curl_pgrsUpdate(data)) - return CURLE_ABORTED_BY_CALLBACK; - - result = Curl_speedcheck(data, now); + result = Curl_pgrsCheck(data); if(result) break; - left = Curl_timeleft(data, NULL, FALSE); - if(left < 0) { + left_ms = Curl_timeleft_ms(data, FALSE); + if(left_ms < 0) { failf(data, "Operation timed out"); return CURLE_OPERATION_TIMEDOUT; } } - else if(curlx_timediff(now, dis) > 1000) { + else if(curlx_ptimediff_ms(Curl_pgrs_now(data), &start) > 1000) { /* disconnect timeout */ failf(data, "Disconnect timed out"); result = CURLE_OK; @@ -3170,7 +3153,7 @@ static CURLcode ssh_block_statemach(struct Curl_easy *data, fd_write = sock; /* wait for the socket to become ready */ (void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write, - left > 1000 ? 1000 : left); + left_ms > 1000 ? 1000 : left_ms); } } @@ -3185,7 +3168,7 @@ static void myssh_easy_dtor(void *key, size_t klen, void *entry) Curl_safefree(sshp->path); curlx_dyn_free(&sshp->readdir); curlx_dyn_free(&sshp->readdir_link); - free(sshp); + curlx_free(sshp); } static void myssh_conn_dtor(void *key, size_t klen, void *entry) @@ -3194,7 +3177,7 @@ static void myssh_conn_dtor(void *key, size_t klen, void *entry) (void)key; (void)klen; sshc_cleanup(sshc, NULL, TRUE); - free(sshc); + curlx_free(sshc); } /* @@ -3207,14 +3190,14 @@ static CURLcode ssh_setup_connection(struct Curl_easy *data, struct SSHPROTO *sshp; (void)conn; - sshc = calloc(1, sizeof(*sshc)); + sshc = curlx_calloc(1, sizeof(*sshc)); if(!sshc) return CURLE_OUT_OF_MEMORY; if(Curl_conn_meta_set(conn, CURL_META_SSH_CONN, sshc, myssh_conn_dtor)) return CURLE_OUT_OF_MEMORY; - sshp = calloc(1, sizeof(*sshp)); + sshp = curlx_calloc(1, sizeof(*sshp)); if(!sshp) return CURLE_OUT_OF_MEMORY; @@ -3304,24 +3287,24 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done) { const char *crypto_str; switch(libssh2_crypto_engine()) { - case libssh2_gcrypt: - crypto_str = "libgcrypt"; - break; - case libssh2_mbedtls: - crypto_str = "mbedTLS"; - break; - case libssh2_openssl: - crypto_str = "openssl compatible"; - break; - case libssh2_os400qc3: - crypto_str = "OS400QC3"; - break; - case libssh2_wincng: - crypto_str = "WinCNG"; - break; - default: - crypto_str = NULL; - break; + case libssh2_gcrypt: + crypto_str = "libgcrypt"; + break; + case libssh2_mbedtls: + crypto_str = "mbedTLS"; + break; + case libssh2_openssl: + crypto_str = "openssl compatible"; + break; + case libssh2_os400qc3: + crypto_str = "OS400QC3"; + break; + case libssh2_wincng: + crypto_str = "WinCNG"; + break; + default: + crypto_str = NULL; + break; } if(crypto_str) infof(data, "libssh2 cryptography backend: %s", crypto_str); @@ -3331,10 +3314,6 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done) if(!sshc) return CURLE_FAILED_INIT; - /* We default to persistent connections. We set this already in this connect - function to make the reuse checks properly be able to check this bit. */ - connkeep(conn, "SSH default"); - infof(data, "User: '%s'", conn->user); #ifdef CURL_LIBSSH2_DEBUG infof(data, "Password: %s", conn->passwd); @@ -3476,15 +3455,14 @@ static CURLcode ssh_connect(struct Curl_easy *data, bool *done) * the options previously setup. */ -static -CURLcode scp_perform(struct Curl_easy *data, - bool *connected, - bool *dophase_done) +static CURLcode scp_perform(struct Curl_easy *data, + bool *connected, + bool *dophase_done) { struct ssh_conn *sshc = Curl_conn_meta_get(data->conn, CURL_META_SSH_CONN); CURLcode result = CURLE_OK; - DEBUGF(infof(data, "DO phase starts")); + CURL_TRC_SSH(data, "DO phase starts"); *dophase_done = FALSE; /* not done yet */ if(!sshc) @@ -3499,7 +3477,7 @@ CURLcode scp_perform(struct Curl_easy *data, *connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET); if(*dophase_done) { - DEBUGF(infof(data, "DO phase is complete")); + CURL_TRC_SSH(data, "DO phase is complete"); } return result; @@ -3513,7 +3491,7 @@ static CURLcode scp_doing(struct Curl_easy *data, result = ssh_multi_statemach(data, dophase_done); if(*dophase_done) { - DEBUGF(infof(data, "DO phase is complete")); + CURL_TRC_SSH(data, "DO phase is complete"); } return result; } @@ -3535,18 +3513,15 @@ static CURLcode ssh_do(struct Curl_easy *data, bool *done) return CURLE_FAILED_INIT; data->req.size = -1; /* make sure this is unknown at this point */ - sshc->secondCreateDirs = 0; /* reset the create dir attempt state + sshc->secondCreateDirs = 0; /* reset the create directory attempt state variable */ - Curl_pgrsSetUploadCounter(data, 0); - Curl_pgrsSetDownloadCounter(data, 0); - Curl_pgrsSetUploadSize(data, -1); - Curl_pgrsSetDownloadSize(data, -1); + Curl_pgrsReset(data); if(conn->handler->protocol & CURLPROTO_SCP) - result = scp_perform(data, &connected, done); + result = scp_perform(data, &connected, done); else - result = sftp_perform(data, &connected, done); + result = sftp_perform(data, &connected, done); return result; } @@ -3563,16 +3538,15 @@ static CURLcode sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data, if(sshc->ssh_agent) { rc = libssh2_agent_disconnect(sshc->ssh_agent); - if(!block && (rc == LIBSSH2_ERROR_EAGAIN)) - return CURLE_AGAIN; - if((rc < 0) && data) { char *err_msg = NULL; - (void)libssh2_session_last_error(sshc->ssh_session, - &err_msg, NULL, 0); + (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); infof(data, "Failed to disconnect from libssh2 agent: %d %s", rc, err_msg); } + if(!block && (rc == LIBSSH2_ERROR_EAGAIN)) + return CURLE_AGAIN; + libssh2_agent_free(sshc->ssh_agent); sshc->ssh_agent = NULL; @@ -3584,54 +3558,53 @@ static CURLcode sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data, if(sshc->sftp_handle) { rc = libssh2_sftp_close(sshc->sftp_handle); - if(!block && (rc == LIBSSH2_ERROR_EAGAIN)) - return CURLE_AGAIN; - if((rc < 0) && data) { char *err_msg = NULL; - (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, - NULL, 0); + (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg); } + if(!block && (rc == LIBSSH2_ERROR_EAGAIN)) + return CURLE_AGAIN; + sshc->sftp_handle = NULL; } if(sshc->ssh_channel) { rc = libssh2_channel_free(sshc->ssh_channel); - if(!block && (rc == LIBSSH2_ERROR_EAGAIN)) - return CURLE_AGAIN; - if((rc < 0) && data) { char *err_msg = NULL; - (void)libssh2_session_last_error(sshc->ssh_session, - &err_msg, NULL, 0); - infof(data, "Failed to free libssh2 scp subsystem: %d %s", - rc, err_msg); + (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); + infof(data, "Failed to free libssh2 scp subsystem: %d %s", rc, err_msg); } + if(!block && (rc == LIBSSH2_ERROR_EAGAIN)) + return CURLE_AGAIN; + sshc->ssh_channel = NULL; } if(sshc->sftp_session) { rc = libssh2_sftp_shutdown(sshc->sftp_session); + if((rc < 0) && data) { + char *err_msg = NULL; + (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); + infof(data, "Failed to stop libssh2 sftp subsystem: %d %s", rc, err_msg); + } if(!block && (rc == LIBSSH2_ERROR_EAGAIN)) return CURLE_AGAIN; - if((rc < 0) && data) - infof(data, "Failed to stop libssh2 sftp subsystem"); sshc->sftp_session = NULL; } if(sshc->ssh_session) { rc = libssh2_session_free(sshc->ssh_session); - if(!block && (rc == LIBSSH2_ERROR_EAGAIN)) - return CURLE_AGAIN; - if((rc < 0) && data) { char *err_msg = NULL; - (void)libssh2_session_last_error(sshc->ssh_session, - &err_msg, NULL, 0); + (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0); infof(data, "Failed to free libssh2 session: %d %s", rc, err_msg); } + if(!block && (rc == LIBSSH2_ERROR_EAGAIN)) + return CURLE_AGAIN; + sshc->ssh_session = NULL; } @@ -3652,7 +3625,6 @@ static CURLcode sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data, return CURLE_OK; } - /* BLOCKING, but the function is using the state machine so the only reason this is still blocking is that the multi interface code has no support for disconnecting operations that takes a while */ @@ -3665,7 +3637,7 @@ static CURLcode scp_disconnect(struct Curl_easy *data, struct SSHPROTO *sshp = Curl_meta_get(data, CURL_META_SSH_EASY); (void)dead_connection; - if(sshc && sshc->ssh_session && sshp) { + if(sshc && sshc->ssh_session) { /* only if there is a session still around to use! */ myssh_state(data, sshc, SSH_SESSION_DISCONNECT); result = ssh_block_statemach(data, sshc, sshp, TRUE); @@ -3700,7 +3672,6 @@ static CURLcode ssh_done(struct Curl_easy *data, CURLcode status) return result; } - static CURLcode scp_done(struct Curl_easy *data, CURLcode status, bool premature) { @@ -3714,7 +3685,7 @@ static CURLcode scp_done(struct Curl_easy *data, CURLcode status, } static CURLcode scp_send(struct Curl_easy *data, int sockindex, - const void *mem, size_t len, bool eos, + const uint8_t *mem, size_t len, bool eos, size_t *pnwritten) { struct connectdata *conn = data->conn; @@ -3730,7 +3701,8 @@ static CURLcode scp_send(struct Curl_easy *data, int sockindex, return CURLE_FAILED_INIT; /* libssh2_channel_write() returns int! */ - nwritten = (ssize_t) libssh2_channel_write(sshc->ssh_channel, mem, len); + nwritten = (ssize_t)libssh2_channel_write(sshc->ssh_channel, + (const char *)mem, len); ssh_block2waitfor(data, sshc, (nwritten == LIBSSH2_ERROR_EAGAIN)); @@ -3759,7 +3731,7 @@ static CURLcode scp_recv(struct Curl_easy *data, int sockindex, return CURLE_FAILED_INIT; /* libssh2_channel_read() returns int */ - nread = (ssize_t) libssh2_channel_read(sshc->ssh_channel, mem, len); + nread = (ssize_t)libssh2_channel_read(sshc->ssh_channel, mem, len); ssh_block2waitfor(data, sshc, (nread == LIBSSH2_ERROR_EAGAIN)); if(nread == LIBSSH2_ERROR_EAGAIN) @@ -3785,15 +3757,14 @@ static CURLcode scp_recv(struct Curl_easy *data, int sockindex, * the options previously setup. */ -static -CURLcode sftp_perform(struct Curl_easy *data, - bool *connected, - bool *dophase_done) +static CURLcode sftp_perform(struct Curl_easy *data, + bool *connected, + bool *dophase_done) { struct ssh_conn *sshc = Curl_conn_meta_get(data->conn, CURL_META_SSH_CONN); CURLcode result = CURLE_OK; - DEBUGF(infof(data, "DO phase starts")); + CURL_TRC_SSH(data, "DO phase starts"); *dophase_done = FALSE; /* not done yet */ if(!sshc) @@ -3808,7 +3779,7 @@ CURLcode sftp_perform(struct Curl_easy *data, *connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET); if(*dophase_done) { - DEBUGF(infof(data, "DO phase is complete")); + CURL_TRC_SSH(data, "DO phase is complete"); } return result; @@ -3821,7 +3792,7 @@ static CURLcode sftp_doing(struct Curl_easy *data, CURLcode result = ssh_multi_statemach(data, dophase_done); if(*dophase_done) { - DEBUGF(infof(data, "DO phase is complete")); + CURL_TRC_SSH(data, "DO phase is complete"); } return result; } @@ -3837,20 +3808,17 @@ static CURLcode sftp_disconnect(struct Curl_easy *data, struct SSHPROTO *sshp = Curl_meta_get(data, CURL_META_SSH_EASY); (void)dead_connection; - DEBUGF(infof(data, "SSH DISCONNECT starts now")); - - if(sshc && sshc->ssh_session && sshp) { - /* only if there is a session still around to use! */ - myssh_state(data, sshc, SSH_SFTP_SHUTDOWN); - result = ssh_block_statemach(data, sshc, sshp, TRUE); - } - - DEBUGF(infof(data, "SSH DISCONNECT is done")); - if(sshc) + if(sshc) { + if(sshc->ssh_session) { + /* only if there is a session still around to use! */ + CURL_TRC_SSH(data, "DISCONNECT starts now"); + myssh_state(data, sshc, SSH_SFTP_SHUTDOWN); + result = ssh_block_statemach(data, sshc, sshp, TRUE); + CURL_TRC_SSH(data, "DISCONNECT is done -> %d", result); + } sshc_cleanup(sshc, data, TRUE); - + } return result; - } static CURLcode sftp_done(struct Curl_easy *data, CURLcode status, @@ -3875,7 +3843,7 @@ static CURLcode sftp_done(struct Curl_easy *data, CURLcode status, /* return number of sent bytes */ static CURLcode sftp_send(struct Curl_easy *data, int sockindex, - const void *mem, size_t len, bool eos, + const uint8_t *mem, size_t len, bool eos, size_t *pnwritten) { struct connectdata *conn = data->conn; @@ -3889,7 +3857,7 @@ static CURLcode sftp_send(struct Curl_easy *data, int sockindex, if(!sshc) return CURLE_FAILED_INIT; - nwrite = libssh2_sftp_write(sshc->sftp_handle, mem, len); + nwrite = libssh2_sftp_write(sshc->sftp_handle, (const char *)mem, len); ssh_block2waitfor(data, sshc, (nwrite == LIBSSH2_ERROR_EAGAIN)); @@ -3934,65 +3902,65 @@ static CURLcode sftp_recv(struct Curl_easy *data, int sockindex, static const char *sftp_libssh2_strerror(unsigned long err) { switch(err) { - case LIBSSH2_FX_NO_SUCH_FILE: - return "No such file or directory"; + case LIBSSH2_FX_NO_SUCH_FILE: + return "No such file or directory"; - case LIBSSH2_FX_PERMISSION_DENIED: - return "Permission denied"; + case LIBSSH2_FX_PERMISSION_DENIED: + return "Permission denied"; - case LIBSSH2_FX_FAILURE: - return "Operation failed"; + case LIBSSH2_FX_FAILURE: + return "Operation failed"; - case LIBSSH2_FX_BAD_MESSAGE: - return "Bad message from SFTP server"; + case LIBSSH2_FX_BAD_MESSAGE: + return "Bad message from SFTP server"; - case LIBSSH2_FX_NO_CONNECTION: - return "Not connected to SFTP server"; + case LIBSSH2_FX_NO_CONNECTION: + return "Not connected to SFTP server"; - case LIBSSH2_FX_CONNECTION_LOST: - return "Connection to SFTP server lost"; + case LIBSSH2_FX_CONNECTION_LOST: + return "Connection to SFTP server lost"; - case LIBSSH2_FX_OP_UNSUPPORTED: - return "Operation not supported by SFTP server"; + case LIBSSH2_FX_OP_UNSUPPORTED: + return "Operation not supported by SFTP server"; - case LIBSSH2_FX_INVALID_HANDLE: - return "Invalid handle"; + case LIBSSH2_FX_INVALID_HANDLE: + return "Invalid handle"; - case LIBSSH2_FX_NO_SUCH_PATH: - return "No such file or directory"; + case LIBSSH2_FX_NO_SUCH_PATH: + return "No such file or directory"; - case LIBSSH2_FX_FILE_ALREADY_EXISTS: - return "File already exists"; + case LIBSSH2_FX_FILE_ALREADY_EXISTS: + return "File already exists"; - case LIBSSH2_FX_WRITE_PROTECT: - return "File is write protected"; + case LIBSSH2_FX_WRITE_PROTECT: + return "File is write protected"; - case LIBSSH2_FX_NO_MEDIA: - return "No media"; + case LIBSSH2_FX_NO_MEDIA: + return "No media"; - case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM: - return "Disk full"; + case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM: + return "Disk full"; - case LIBSSH2_FX_QUOTA_EXCEEDED: - return "User quota exceeded"; + case LIBSSH2_FX_QUOTA_EXCEEDED: + return "User quota exceeded"; - case LIBSSH2_FX_UNKNOWN_PRINCIPLE: - return "Unknown principle"; + case LIBSSH2_FX_UNKNOWN_PRINCIPLE: + return "Unknown principle"; - case LIBSSH2_FX_LOCK_CONFlICT: - return "File lock conflict"; + case LIBSSH2_FX_LOCK_CONFlICT: + return "File lock conflict"; - case LIBSSH2_FX_DIR_NOT_EMPTY: - return "Directory not empty"; + case LIBSSH2_FX_DIR_NOT_EMPTY: + return "Directory not empty"; - case LIBSSH2_FX_NOT_A_DIRECTORY: - return "Not a directory"; + case LIBSSH2_FX_NOT_A_DIRECTORY: + return "Not a directory"; - case LIBSSH2_FX_INVALID_FILENAME: - return "Invalid filename"; + case LIBSSH2_FX_INVALID_FILENAME: + return "Invalid filename"; - case LIBSSH2_FX_LINK_LOOP: - return "Link points to itself"; + case LIBSSH2_FX_LINK_LOOP: + return "Link points to itself"; } return "Unknown error in libssh2"; } diff --git a/lib/vssh/ssh.h b/lib/vssh/ssh.h index e09111e63f66..ad0875f19143 100644 --- a/lib/vssh/ssh.h +++ b/lib/vssh/ssh.h @@ -36,7 +36,7 @@ #include #endif -#include "curl_path.h" +#include "vssh.h" /* meta key for storing protocol meta at easy handle */ #define CURL_META_SSH_EASY "meta:proto:ssh:easy" @@ -149,14 +149,15 @@ struct ssh_conn { char *quote_path1; /* two generic pointers for the QUOTE stuff */ char *quote_path2; - char *homedir; /* when doing SFTP we figure out home dir in the - connect phase */ + char *homedir; /* when doing SFTP we figure out home directory + in the connect phase */ /* end of READDIR stuff */ int secondCreateDirs; /* counter use by the code to see if the second attempt has been made to change to/create a directory */ - int orig_waitfor; /* default READ/WRITE bits wait for */ + int waitfor; /* KEEP_RECV/KEEP_SEND bits overriding + pollset given flags */ char *slash_pos; /* used by the SFTP_CREATE_DIRS state */ #ifdef USE_LIBSSH @@ -216,7 +217,7 @@ struct ssh_conn { #ifdef USE_LIBSSH #if LIBSSH_VERSION_INT < SSH_VERSION_INT(0, 9, 0) -# error "SCP/SFTP protocols require libssh 0.9.0 or later" +#error "SCP/SFTP protocols require libssh 0.9.0 or later" #endif #endif @@ -226,7 +227,7 @@ struct ssh_conn { non-configure platforms */ #if !defined(LIBSSH2_VERSION_NUM) || (LIBSSH2_VERSION_NUM < 0x010208) -# error "SCP/SFTP protocols require libssh2 1.2.8 or later" +#error "SCP/SFTP protocols require libssh2 1.2.8 or later" /* 1.2.8 was released on April 5 2011 */ #endif @@ -246,7 +247,7 @@ void Curl_ssh_attach(struct Curl_easy *data, #else /* for non-SSH builds */ #define Curl_ssh_cleanup() -#define Curl_ssh_attach(x,y) +#define Curl_ssh_attach(x, y) #define Curl_ssh_init() 0 #endif diff --git a/lib/vssh/curl_path.c b/lib/vssh/vssh.c similarity index 63% rename from lib/vssh/curl_path.c rename to lib/vssh/vssh.c index 7a0e5bffef20..d322643eb408 100644 --- a/lib/vssh/curl_path.c +++ b/lib/vssh/vssh.c @@ -26,11 +26,10 @@ #ifdef USE_SSH -#include "curl_path.h" -#include -#include "../curl_memory.h" +#include "vssh.h" +#include "../curlx/strparse.h" +#include "../curl_trc.h" #include "../escape.h" -#include "../memdebug.h" #define MAX_SSHPATH_LEN 100000 /* arbitrary */ @@ -57,7 +56,7 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data, (working_path_len > 3) && (!memcmp(working_path, "/~/", 3))) { /* It is referenced to the home directory, so strip the leading '/~/' */ if(curlx_dyn_addn(&npath, &working_path[3], working_path_len - 3)) { - free(working_path); + curlx_free(working_path); return CURLE_OUT_OF_MEMORY; } } @@ -65,7 +64,7 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data, (!strcmp("/~", working_path) || ((working_path_len > 2) && !memcmp(working_path, "/~/", 3)))) { if(curlx_dyn_add(&npath, homedir)) { - free(working_path); + curlx_free(working_path); return CURLE_OUT_OF_MEMORY; } if(working_path_len > 2) { @@ -75,25 +74,25 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data, /* Copy a separating '/' if homedir does not end with one */ len = curlx_dyn_len(&npath); p = curlx_dyn_ptr(&npath); - if(len && (p[len-1] != '/')) + if(len && (p[len - 1] != '/')) copyfrom = 2; if(curlx_dyn_addn(&npath, &working_path[copyfrom], working_path_len - copyfrom)) { - free(working_path); + curlx_free(working_path); return CURLE_OUT_OF_MEMORY; } } else { if(curlx_dyn_add(&npath, "/")) { - free(working_path); + curlx_free(working_path); return CURLE_OUT_OF_MEMORY; } } } if(curlx_dyn_len(&npath)) { - free(working_path); + curlx_free(working_path); /* store the pointer for the caller to receive */ *path = curlx_dyn_ptr(&npath); @@ -105,32 +104,11 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data, return CURLE_OK; } -/* The original get_pathname() function came from OpenSSH sftp.c version - 4.6p1. */ -/* - * Copyright (c) 2001-2004 Damien Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - #define MAX_PATHLENGTH 65535 /* arbitrary long */ CURLcode Curl_get_pathname(const char **cpp, char **path, const char *homedir) { - const char *cp = *cpp, *end; - char quot; - unsigned int i; - static const char WHITESPACE[] = " \t\r\n"; + const char *cp = *cpp; struct dynbuf out; CURLcode result; @@ -143,48 +121,36 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, const char *homedir) curlx_dyn_init(&out, MAX_PATHLENGTH); /* Ignore leading whitespace */ - cp += strspn(cp, WHITESPACE); + curlx_str_passblanks(&cp); /* Check for quoted filenames */ if(*cp == '\"' || *cp == '\'') { - quot = *cp++; + char quot = *cp++; /* Search for terminating quote, unescape some chars */ - for(i = 0; i <= strlen(cp); i++) { - if(cp[i] == quot) { /* Found quote */ - i++; - break; - } - if(cp[i] == '\0') { /* End of string */ + while(*cp != quot) { + if(!*cp) /* End of string */ goto fail; - } - if(cp[i] == '\\') { /* Escaped characters */ - i++; - if(cp[i] != '\'' && cp[i] != '\"' && - cp[i] != '\\') { + + if(*cp == '\\') { /* Escaped characters */ + cp++; + if(*cp != '\'' && *cp != '\"' && *cp != '\\') goto fail; - } } - result = curlx_dyn_addn(&out, &cp[i], 1); + result = curlx_dyn_addn(&out, cp, 1); if(result) return result; + cp++; } + cp++; /* pass the end quote */ if(!curlx_dyn_len(&out)) goto fail; - - /* return pointer to second parameter if it exists */ - *cpp = &cp[i] + strspn(&cp[i], WHITESPACE); } else { - /* Read to end of filename - either to whitespace or terminator */ - end = strpbrk(cp, WHITESPACE); - if(!end) - end = strchr(cp, '\0'); - - /* return pointer to second parameter if it exists */ - *cpp = end + strspn(end, WHITESPACE); - + struct Curl_str word; + bool content = FALSE; + int rc; /* Handling for relative path - prepend home directory */ if(cp[0] == '/' && cp[1] == '~' && cp[2] == '/') { result = curlx_dyn_add(&out, homedir); @@ -193,12 +159,32 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, const char *homedir) if(result) return result; cp += 3; + content = TRUE; + } + /* Read to end of filename - either to whitespace or terminator */ + rc = curlx_str_word(&cp, &word, MAX_PATHLENGTH); + if(rc) { + if(rc == STRE_BIG) { + curlx_dyn_free(&out); + return CURLE_TOO_LARGE; + } + else if(!content) + /* no path, no word, this is incorrect */ + goto fail; + } + else { + /* append the word */ + result = curlx_dyn_addn(&out, curlx_str(&word), curlx_strlen(&word)); + if(result) + return result; } - /* Copy path name up until first "whitespace" */ - result = curlx_dyn_addn(&out, cp, (end - cp)); - if(result) - return result; } + /* skip whitespace */ + curlx_str_passblanks(&cp); + + /* return pointer to second parameter if it exists */ + *cpp = cp; + *path = curlx_dyn_ptr(&out); return CURLE_OK; @@ -207,4 +193,50 @@ CURLcode Curl_get_pathname(const char **cpp, char **path, const char *homedir) return CURLE_QUOTE_ERROR; } +CURLcode Curl_ssh_range(struct Curl_easy *data, + const char *p, curl_off_t filesize, + curl_off_t *startp, curl_off_t *sizep) +{ + curl_off_t from, to; + int to_t; + int from_t = curlx_str_number(&p, &from, CURL_OFF_T_MAX); + if(from_t == STRE_OVERFLOW) + return CURLE_RANGE_ERROR; + curlx_str_passblanks(&p); + (void)curlx_str_single(&p, '-'); + + to_t = curlx_str_numblanks(&p, &to); + if((to_t == STRE_OVERFLOW) || (to_t && from_t) || *p) + return CURLE_RANGE_ERROR; + + if(from_t) { + /* no start point given, set from relative to end of file */ + if(!to) + /* "-0" is not a fine range */ + return CURLE_RANGE_ERROR; + else if(to > filesize) + to = filesize; + from = filesize - to; + to = filesize - 1; + } + else if(from > filesize) { + failf(data, "Offset (%" FMT_OFF_T ") was beyond file size (%" + FMT_OFF_T ")", from, filesize); + return CURLE_RANGE_ERROR; + } + else if((to_t == STRE_NO_NUM) || (to >= filesize)) + to = filesize - 1; + + if(from > to) { + failf(data, "Bad range: start offset larger than end offset"); + return CURLE_RANGE_ERROR; + } + if((to - from) == CURL_OFF_T_MAX) + return CURLE_RANGE_ERROR; + + *startp = from; + *sizep = to - from + 1; + return CURLE_OK; +} + #endif /* if SSH is used */ diff --git a/lib/vssh/curl_path.h b/lib/vssh/vssh.h similarity index 88% rename from lib/vssh/curl_path.h rename to lib/vssh/vssh.h index 1c167f96603a..78de75c9e925 100644 --- a/lib/vssh/curl_path.h +++ b/lib/vssh/vssh.h @@ -25,7 +25,7 @@ ***************************************************************************/ #include "../curl_setup.h" -#include + #include "../urldata.h" CURLcode Curl_getworkingpath(struct Curl_easy *data, @@ -33,4 +33,8 @@ CURLcode Curl_getworkingpath(struct Curl_easy *data, char **path); CURLcode Curl_get_pathname(const char **cpp, char **path, const char *homedir); + +CURLcode Curl_ssh_range(struct Curl_easy *data, + const char *range, curl_off_t filesize, + curl_off_t *startp, curl_off_t *sizep); #endif /* HEADER_CURL_PATH_H */ diff --git a/lib/vtls/apple.c b/lib/vtls/apple.c index 87d5208d735a..9779e11eaac6 100644 --- a/lib/vtls/apple.c +++ b/lib/vtls/apple.c @@ -50,39 +50,35 @@ #include #endif -/* The last #include files should be: */ -#include "../curl_memory.h" -#include "../memdebug.h" - #ifdef USE_APPLE_SECTRUST #define SSL_SYSTEM_VERIFIER -#if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) \ - && MAC_OS_X_VERSION_MAX_ALLOWED >= 101400) \ - || (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) \ - && __IPHONE_OS_VERSION_MAX_ALLOWED >= 120000) +#if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) && \ + MAC_OS_X_VERSION_MAX_ALLOWED >= 101400) || \ + (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \ + __IPHONE_OS_VERSION_MAX_ALLOWED >= 120000) #define SUPPORTS_SecTrustEvaluateWithError 1 #endif -#if defined(SUPPORTS_SecTrustEvaluateWithError) \ - && ((defined(MAC_OS_X_VERSION_MIN_REQUIRED) \ - && MAC_OS_X_VERSION_MIN_REQUIRED >= 101400) \ - || (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) \ - && __IPHONE_OS_VERSION_MIN_REQUIRED >= 120000)) +#if defined(SUPPORTS_SecTrustEvaluateWithError) && \ + ((defined(MAC_OS_X_VERSION_MIN_REQUIRED) && \ + MAC_OS_X_VERSION_MIN_REQUIRED >= 101400) || \ + (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && \ + __IPHONE_OS_VERSION_MIN_REQUIRED >= 120000)) #define REQUIRES_SecTrustEvaluateWithError 1 #endif -#if defined(SUPPORTS_SecTrustEvaluateWithError) \ - && !defined(HAVE_BUILTIN_AVAILABLE) \ - && !defined(REQUIRES_SecTrustEvaluateWithError) +#if defined(SUPPORTS_SecTrustEvaluateWithError) && \ + !defined(HAVE_BUILTIN_AVAILABLE) && \ + !defined(REQUIRES_SecTrustEvaluateWithError) #undef SUPPORTS_SecTrustEvaluateWithError #endif -#if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) \ - && MAC_OS_X_VERSION_MAX_ALLOWED >= 100900) \ - || (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) \ - && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000) +#if (defined(MAC_OS_X_VERSION_MAX_ALLOWED) && \ + MAC_OS_X_VERSION_MAX_ALLOWED >= 100900) || \ + (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && \ + __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000) #define SUPPORTS_SecOCSP 1 #endif @@ -148,7 +144,7 @@ CURLcode Curl_vtls_apple_verify(struct Curl_cfilter *cf, * add `kSecRevocationRequirePositiveResponse` to the Apple * Trust policies, it interprets this as it NEEDs a confirmation * of a cert being NOT REVOKED. Which not in general available for - * certificates on the internet. + * certificates on the Internet. * It seems that applications using this policy are expected to PIN * their certificate public keys or verification will fail. * This does not seem to be what we want here. */ @@ -211,8 +207,7 @@ CURLcode Curl_vtls_apple_verify(struct Curl_cfilter *cf, #if defined(HAVE_BUILTIN_AVAILABLE) && defined(SUPPORTS_SecOCSP) if(ocsp_len > 0) { if(__builtin_available(macOS 10.9, iOS 7, tvOS 9, watchOS 2, *)) { - CFDataRef ocspdata = - CFDataCreate(NULL, ocsp_buf, (CFIndex)ocsp_len); + CFDataRef ocspdata = CFDataCreate(NULL, ocsp_buf, (CFIndex)ocsp_len); status = SecTrustSetOCSPResponse(trust, ocspdata); CFRelease(ocspdata); @@ -230,7 +225,7 @@ CURLcode Curl_vtls_apple_verify(struct Curl_cfilter *cf, #endif #ifdef SUPPORTS_SecTrustEvaluateWithError -#if defined(HAVE_BUILTIN_AVAILABLE) +#ifdef HAVE_BUILTIN_AVAILABLE if(__builtin_available(macOS 10.14, iOS 12, tvOS 12, watchOS 5, *)) { #else if(1) { @@ -244,11 +239,11 @@ CURLcode Curl_vtls_apple_verify(struct Curl_cfilter *cf, if(error_ref) { CFIndex size = CFStringGetMaximumSizeForEncoding( CFStringGetLength(error_ref), kCFStringEncodingUTF8); - err_desc = malloc(size + 1); + err_desc = curlx_malloc(size + 1); if(err_desc) { if(!CFStringGetCString(error_ref, err_desc, size, - kCFStringEncodingUTF8)) { - free(err_desc); + kCFStringEncodingUTF8)) { + curlx_free(err_desc); err_desc = NULL; } } @@ -266,17 +261,22 @@ CURLcode Curl_vtls_apple_verify(struct Curl_cfilter *cf, if(status != noErr) { failf(data, "Apple SecTrust verification failed: error %i", (int)status); + result = CURLE_PEER_FAILED_VERIFICATION; } else if((sec_result == kSecTrustResultUnspecified) || (sec_result == kSecTrustResultProceed)) { /* "unspecified" means system-trusted with no explicit user setting */ result = CURLE_OK; } + else { + /* Any other trust result is a verification failure in this context */ + result = CURLE_PEER_FAILED_VERIFICATION; + } #endif /* REQUIRES_SecTrustEvaluateWithError */ } out: - free(err_desc); + curlx_free(err_desc); if(error_ref) CFRelease(error_ref); if(error) diff --git a/lib/vtls/cipher_suite.c b/lib/vtls/cipher_suite.c index 23fb3a3c5d16..c026bdee9134 100644 --- a/lib/vtls/cipher_suite.c +++ b/lib/vtls/cipher_suite.c @@ -25,7 +25,6 @@ #if defined(USE_MBEDTLS) || defined(USE_RUSTLS) #include "cipher_suite.h" -#include /* * To support the CURLOPT_SSL_CIPHER_LIST option on SSL backends @@ -157,7 +156,7 @@ struct cs_entry { }; /* !checksrc! disable COMMANOSPACE all */ -static const struct cs_entry cs_list [] = { +static const struct cs_entry cs_list[] = { /* TLS 1.3 ciphers */ #if defined(USE_MBEDTLS) || defined(USE_RUSTLS) CS_ENTRY(0x1301, TLS,AES,128,GCM,SHA256,,,), @@ -547,10 +546,9 @@ static const struct cs_entry cs_list [] = { }; #define CS_LIST_LEN CURL_ARRAYSIZE(cs_list) -static int cs_str_to_zip(const char *cs_str, size_t cs_len, - uint8_t zip[6]) +static int cs_str_to_zip(const char *cs_str, size_t cs_len, uint8_t zip[6]) { - uint8_t indexes[8] = {0}; + uint8_t indexes[8] = { 0 }; const char *entry, *cur; const char *nxt = cs_str; const char *end = cs_str + cs_len; @@ -568,7 +566,8 @@ static int cs_str_to_zip(const char *cs_str, size_t cs_len, /* determine the length of the part */ cur = nxt; - for(; nxt < end && *nxt != '\0' && *nxt != separator; nxt++); + for(; nxt < end && *nxt != '\0' && *nxt != separator; nxt++) + ; len = nxt - cur; /* lookup index for the part (skip empty string at 0) */ @@ -581,24 +580,23 @@ static int cs_str_to_zip(const char *cs_str, size_t cs_len, if(idx == CS_TXT_LEN) return -1; - indexes[i++] = (uint8_t) idx; + indexes[i++] = (uint8_t)idx; } while(nxt < end && *(nxt++) != '\0'); /* zip the 8 indexes into 48 bits */ - zip[0] = (uint8_t) (indexes[0] << 2 | (indexes[1] & 0x3F) >> 4); - zip[1] = (uint8_t) (indexes[1] << 4 | (indexes[2] & 0x3F) >> 2); - zip[2] = (uint8_t) (indexes[2] << 6 | (indexes[3] & 0x3F)); - zip[3] = (uint8_t) (indexes[4] << 2 | (indexes[5] & 0x3F) >> 4); - zip[4] = (uint8_t) (indexes[5] << 4 | (indexes[6] & 0x3F) >> 2); - zip[5] = (uint8_t) (indexes[6] << 6 | (indexes[7] & 0x3F)); + zip[0] = (uint8_t)(indexes[0] << 2 | (indexes[1] & 0x3F) >> 4); + zip[1] = (uint8_t)(indexes[1] << 4 | (indexes[2] & 0x3F) >> 2); + zip[2] = (uint8_t)(indexes[2] << 6 | (indexes[3] & 0x3F)); + zip[3] = (uint8_t)(indexes[4] << 2 | (indexes[5] & 0x3F) >> 4); + zip[4] = (uint8_t)(indexes[5] << 4 | (indexes[6] & 0x3F) >> 2); + zip[5] = (uint8_t)(indexes[6] << 6 | (indexes[7] & 0x3F)); return 0; } -static int cs_zip_to_str(const uint8_t zip[6], - char *buf, size_t buf_size) +static int cs_zip_to_str(const uint8_t zip[6], char *buf, size_t buf_size) { - uint8_t indexes[8] = {0}; + uint8_t indexes[8] = { 0 }; const char *entry; char separator = '-'; int idx, i, r; @@ -659,13 +657,12 @@ uint16_t Curl_cipher_suite_lookup_id(const char *cs_str, size_t cs_len) static bool cs_is_separator(char c) { switch(c) { - case ' ': - case '\t': - case ':': - case ',': - case ';': - return TRUE; - default:; + case ' ': + case '\t': + case ':': + case ',': + case ';': + return TRUE; } return FALSE; } @@ -673,10 +670,12 @@ static bool cs_is_separator(char c) uint16_t Curl_cipher_suite_walk_str(const char **str, const char **end) { /* move string pointer to first non-separator or end of string */ - for(; cs_is_separator(*str[0]); (*str)++); + for(; cs_is_separator(*str[0]); (*str)++) + ; /* move end pointer to next separator or end of string */ - for(*end = *str; *end[0] != '\0' && !cs_is_separator(*end[0]); (*end)++); + for(*end = *str; *end[0] != '\0' && !cs_is_separator(*end[0]); (*end)++) + ; return Curl_cipher_suite_lookup_id(*str, *end - *str); } diff --git a/lib/vtls/gtls.c b/lib/vtls/gtls.c index 1c0a6fb2d610..dbc72c521d4a 100644 --- a/lib/vtls/gtls.c +++ b/lib/vtls/gtls.c @@ -41,8 +41,7 @@ #include #include "../urldata.h" -#include "../sendf.h" -#include "../curlx/inet_pton.h" +#include "../curl_trc.h" #include "keylog.h" #include "gtls.h" #include "vtls.h" @@ -53,15 +52,10 @@ #include "../parsedate.h" #include "../connect.h" /* for the connect timeout */ #include "../progress.h" -#include "../select.h" #include "../strdup.h" #include "../curlx/fopen.h" -#include "../curlx/warnless.h" +#include "../curlx/timeval.h" #include "x509asn1.h" -#include "../multiif.h" -#include "../curl_memory.h" -/* The last #include file should be: */ -#include "../memdebug.h" /* Enable GnuTLS debugging by defining GTLSDEBUG */ /*#define GTLSDEBUG */ @@ -69,12 +63,11 @@ #ifdef GTLSDEBUG static void tls_log_func(int level, const char *str) { - curl_mfprintf(stderr, "|<%d>| %s", level, str); + curl_mfprintf(stderr, "|<%d>| %s", level, str); } #endif -static bool gtls_inited = FALSE; -#if !defined(GNUTLS_VERSION_NUMBER) || (GNUTLS_VERSION_NUMBER < 0x03010a) +#if !defined(GNUTLS_VERSION_NUMBER) || (GNUTLS_VERSION_NUMBER < 0x030605) #error "too old GnuTLS version" #endif @@ -135,8 +128,7 @@ static ssize_t gtls_pull(void *s, void *buf, size_t blen) } result = Curl_conn_cf_recv(cf->next, data, buf, blen, &nread); - CURL_TRC_CF(data, cf, "glts_pull(len=%zu) -> %d, %zd", - blen, result, nread); + CURL_TRC_CF(data, cf, "glts_pull(len=%zu) -> %d, %zd", blen, result, nread); backend->gtls.io_result = result; if(result) { /* !checksrc! disable ERRNOVAR 1 */ @@ -149,44 +141,41 @@ static ssize_t gtls_pull(void *s, void *buf, size_t blen) return (ssize_t)nread; } -/* gtls_init() +/** + * gtls_init() * * Global GnuTLS init, called from Curl_ssl_init(). This calls functions that - * are not thread-safe and thus this function itself is not thread-safe and - * must only be called from within curl_global_init() to keep the thread - * situation under control! + * are not thread-safe (It is thread-safe since GnuTLS 3.3.0) and thus this + * function itself is not thread-safe and must only be called from within + * curl_global_init() to keep the thread situation under control! + * + * @retval 0 error initializing SSL + * @retval 1 SSL initialized successfully */ static int gtls_init(void) { int ret = 1; - if(!gtls_inited) { - ret = gnutls_global_init() ? 0 : 1; + ret = gnutls_global_init() ? 0 : 1; #ifdef GTLSDEBUG - gnutls_global_set_log_function(tls_log_func); - gnutls_global_set_log_level(2); + gnutls_global_set_log_function(tls_log_func); + gnutls_global_set_log_level(2); #endif - gtls_inited = TRUE; - } return ret; } static void gtls_cleanup(void) { - if(gtls_inited) { - gnutls_global_deinit(); - gtls_inited = FALSE; - } + gnutls_global_deinit(); + Curl_tls_keylog_close(); } #ifndef CURL_DISABLE_VERBOSE_STRINGS -static void showtime(struct Curl_easy *data, - const char *text, - time_t stamp) +static void showtime(struct Curl_easy *data, const char *text, time_t stamp) { struct tm buffer; const struct tm *tm = &buffer; char str[96]; - CURLcode result = Curl_gmtime(stamp, &buffer); + CURLcode result = curlx_gmtime(stamp, &buffer); if(result) return; @@ -215,13 +204,13 @@ static gnutls_datum_t load_file(const char *file) f = curlx_fopen(file, "rb"); if(!f) return loaded_file; - if(fseek(f, 0, SEEK_END) != 0 - || (filelen = ftell(f)) < 0 - || fseek(f, 0, SEEK_SET) != 0 - || !(ptr = malloc((size_t)filelen))) + if(fseek(f, 0, SEEK_END) != 0 || + (filelen = ftell(f)) < 0 || + fseek(f, 0, SEEK_SET) != 0 || + !(ptr = curlx_malloc((size_t)filelen))) goto out; if(fread(ptr, 1, (size_t)filelen, f) < (size_t)filelen) { - free(ptr); + curlx_free(ptr); goto out; } @@ -234,13 +223,12 @@ static gnutls_datum_t load_file(const char *file) static void unload_file(gnutls_datum_t data) { - free(data.data); + curlx_free(data.data); } - /* this function does an SSL/TLS (re-)handshake */ -static CURLcode handshake(struct Curl_cfilter *cf, - struct Curl_easy *data) +static CURLcode cf_gtls_handshake(struct Curl_cfilter *cf, + struct Curl_easy *data) { struct ssl_connect_data *connssl = cf->ctx; struct gtls_ssl_backend_data *backend = @@ -315,16 +303,17 @@ static gnutls_x509_crt_fmt_t gnutls_do_file_type(const char *type) return GNUTLS_X509_FMT_PEM; /* default to PEM */ } -#define GNUTLS_CIPHERS "NORMAL:-ARCFOUR-128:-CTYPE-ALL:+CTYPE-X509" +#define GNUTLS_CIPHERS "NORMAL:%PROFILE_MEDIUM:-ARCFOUR-128:" \ + "-CTYPE-ALL:+CTYPE-X509" /* If GnuTLS was compiled without support for SRP it will error out if SRP is requested in the priority string, so treat it specially */ #define GNUTLS_SRP "+SRP" #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:" \ + "NORMAL:%PROFILE_MEDIUM:-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" static CURLcode @@ -349,7 +338,7 @@ gnutls_set_ssl_version_min_max(struct Curl_easy *data, if(ssl_version_max < CURL_SSLVERSION_MAX_TLSv1_3) { failf(data, "QUIC needs at least TLS version 1.3"); return CURLE_SSL_CONNECT_ERROR; - } + } *prioritylist = QUIC_PRIORITY; return CURLE_OK; } @@ -396,7 +385,7 @@ gnutls_set_ssl_version_min_max(struct Curl_easy *data, return CURLE_OK; } - failf(data, "GnuTLS: cannot set ssl protocol"); + failf(data, "GnuTLS: cannot set TLS protocol"); return CURLE_SSL_CONNECT_ERROR; } @@ -407,19 +396,19 @@ CURLcode Curl_gtls_shared_creds_create(struct Curl_easy *data, int rc; *pcreds = NULL; - shared = calloc(1, sizeof(*shared)); + shared = curlx_calloc(1, sizeof(*shared)); if(!shared) return CURLE_OUT_OF_MEMORY; rc = gnutls_certificate_allocate_credentials(&shared->creds); if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_cert_all_cred() failed: %s", gnutls_strerror(rc)); - free(shared); + curlx_free(shared); return CURLE_SSL_CONNECT_ERROR; } shared->refcount = 1; - shared->time = curlx_now(); + shared->time = *Curl_pgrs_now(data); *pcreds = shared; return CURLE_OK; } @@ -442,8 +431,8 @@ void Curl_gtls_shared_creds_free(struct gtls_shared_creds **pcreds) --shared->refcount; if(!shared->refcount) { gnutls_certificate_free_credentials(shared->creds); - free(shared->CAfile); - free(shared); + curlx_free(shared->CAfile); + curlx_free(shared); } } } @@ -470,7 +459,7 @@ static CURLcode gtls_populate_creds(struct Curl_cfilter *cf, #else rc = gnutls_certificate_set_x509_system_trust(creds); if(rc < 0) - infof(data, "error reading native ca store (%s), continuing anyway", + infof(data, "error reading native CA store (%s), continuing anyway", gnutls_strerror(rc)); else { infof(data, " Native: %d certificates from system trust", rc); @@ -480,7 +469,31 @@ static CURLcode gtls_populate_creds(struct Curl_cfilter *cf, #endif } - if(config->CAfile) { + if(config->ca_info_blob) { + gnutls_datum_t ca_info_datum; + if(config->ca_info_blob->len > (size_t)UINT_MAX) { + failf(data, "certificate blob too long: %zu bytes", + config->ca_info_blob->len); + return CURLE_SSL_CACERT_BADFILE; + } + ca_info_datum.data = config->ca_info_blob->data; + ca_info_datum.size = (unsigned int)config->ca_info_blob->len; + rc = gnutls_certificate_set_x509_trust_mem(creds, &ca_info_datum, + GNUTLS_X509_FMT_PEM); + creds_are_empty = creds_are_empty && (rc <= 0); + if(rc < 0) { + infof(data, "error reading CA cert blob (%s)%s", gnutls_strerror(rc), + (creds_are_empty ? "" : ", continuing anyway")); + if(creds_are_empty) { + ssl_config->certverifyresult = rc; + return CURLE_SSL_CACERT_BADFILE; + } + } + else + infof(data, " CA Blob: %d certificates", rc); + } + /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */ + else if(config->CAfile) { /* set the trusted CA cert bundle file */ gnutls_certificate_set_verify_flags(creds, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT); @@ -490,7 +503,7 @@ static CURLcode gtls_populate_creds(struct Curl_cfilter *cf, GNUTLS_X509_FMT_PEM); creds_are_empty = creds_are_empty && (rc <= 0); if(rc < 0) { - infof(data, "error reading ca cert file %s (%s)%s", + infof(data, "error reading CA cert file %s (%s)%s", config->CAfile, gnutls_strerror(rc), (creds_are_empty ? "" : ", continuing anyway")); if(creds_are_empty) { @@ -508,7 +521,7 @@ static CURLcode gtls_populate_creds(struct Curl_cfilter *cf, GNUTLS_X509_FMT_PEM); creds_are_empty = creds_are_empty && (rc <= 0); if(rc < 0) { - infof(data, "error reading ca cert file %s (%s)%s", + infof(data, "error reading CA cert file %s (%s)%s", config->CApath, gnutls_strerror(rc), (creds_are_empty ? "" : ", continuing anyway")); if(creds_are_empty) { @@ -528,7 +541,7 @@ static CURLcode gtls_populate_creds(struct Curl_cfilter *cf, rc = gnutls_certificate_set_x509_crl_file(creds, config->CRLfile, GNUTLS_X509_FMT_PEM); if(rc < 0) { - failf(data, "error reading crl file %s (%s)", + failf(data, "error reading CRL file %s (%s)", config->CRLfile, gnutls_strerror(rc)); return CURLE_SSL_CRL_BADFILE; } @@ -542,12 +555,11 @@ static CURLcode gtls_populate_creds(struct Curl_cfilter *cf, /* key to use at `multi->proto_hash` */ #define MPROTO_GTLS_X509_KEY "tls:gtls:x509:share" -static bool gtls_shared_creds_expired(const struct Curl_easy *data, +static bool gtls_shared_creds_expired(struct Curl_easy *data, const struct gtls_shared_creds *sc) { const struct ssl_general_config *cfg = &data->set.general_ssl; - struct curltime now = curlx_now(); - timediff_t elapsed_ms = curlx_timediff(now, sc->time); + timediff_t elapsed_ms = curlx_ptimediff_ms(Curl_pgrs_now(data), &sc->time); timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000; if(timeout_ms < 0) @@ -566,20 +578,20 @@ static bool gtls_shared_creds_different(struct Curl_cfilter *cf, return strcmp(sc->CAfile, conn_config->CAfile); } -static struct gtls_shared_creds* -gtls_get_cached_creds(struct Curl_cfilter *cf, struct Curl_easy *data) +static struct gtls_shared_creds *gtls_get_cached_creds(struct Curl_cfilter *cf, + struct Curl_easy *data) { struct gtls_shared_creds *shared_creds; if(data->multi) { shared_creds = Curl_hash_pick(&data->multi->proto_hash, CURL_UNCONST(MPROTO_GTLS_X509_KEY), - sizeof(MPROTO_GTLS_X509_KEY)-1); - if(shared_creds && shared_creds->creds && - !gtls_shared_creds_expired(data, shared_creds) && - !gtls_shared_creds_different(cf, shared_creds)) { - return shared_creds; - } + sizeof(MPROTO_GTLS_X509_KEY) - 1); + if(shared_creds && shared_creds->creds && + !gtls_shared_creds_expired(data, shared_creds) && + !gtls_shared_creds_different(cf, shared_creds)) { + return shared_creds; + } } return NULL; } @@ -587,7 +599,7 @@ gtls_get_cached_creds(struct Curl_cfilter *cf, struct Curl_easy *data) static void gtls_shared_creds_hash_free(void *key, size_t key_len, void *p) { struct gtls_shared_creds *sc = p; - DEBUGASSERT(key_len == (sizeof(MPROTO_GTLS_X509_KEY)-1)); + DEBUGASSERT(key_len == (sizeof(MPROTO_GTLS_X509_KEY) - 1)); DEBUGASSERT(!memcmp(MPROTO_GTLS_X509_KEY, key, key_len)); (void)key; (void)key_len; @@ -608,7 +620,7 @@ static void gtls_set_cached_creds(struct Curl_cfilter *cf, return; if(conn_config->CAfile) { - sc->CAfile = strdup(conn_config->CAfile); + sc->CAfile = curlx_strdup(conn_config->CAfile); if(!sc->CAfile) return; } @@ -617,9 +629,9 @@ static void gtls_set_cached_creds(struct Curl_cfilter *cf, return; if(!Curl_hash_add2(&data->multi->proto_hash, - CURL_UNCONST(MPROTO_GTLS_X509_KEY), - sizeof(MPROTO_GTLS_X509_KEY)-1, - sc, gtls_shared_creds_hash_free)) { + CURL_UNCONST(MPROTO_GTLS_X509_KEY), + sizeof(MPROTO_GTLS_X509_KEY) - 1, + sc, gtls_shared_creds_hash_free)) { Curl_gtls_shared_creds_free(&sc); /* down reference again */ return; } @@ -636,7 +648,6 @@ CURLcode Curl_gtls_client_trust_setup(struct Curl_cfilter *cf, CURLcode result; int rc; - /* Consider the X509 store cacheable if it comes exclusively from a CAfile, or no source is provided and we are falling back to OpenSSL's built-in default. */ @@ -684,19 +695,18 @@ CURLcode Curl_gtls_cache_session(struct Curl_cfilter *cf, unsigned char *quic_tp, size_t quic_tp_len) { - struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); struct Curl_ssl_session *sc_session; unsigned char *sdata, *qtp_clone = NULL; size_t sdata_len = 0; size_t earlydata_max = 0; CURLcode result = CURLE_OK; - if(!ssl_config->primary.cache_session) + if(!Curl_ssl_scache_use(cf, data)) return CURLE_OK; /* we always unconditionally get the session id here, as even if we already got it from the cache and asked to use it in the connection, it - might've been rejected and then a new one is in use now and we need to + might have been rejected and then a new one is in use now and we need to detect that. */ /* get the session ID data size */ @@ -704,7 +714,7 @@ CURLcode Curl_gtls_cache_session(struct Curl_cfilter *cf, if(!sdata_len) /* gnutls does this for some version combinations */ return CURLE_OK; - sdata = malloc(sdata_len); /* get a buffer for it */ + sdata = curlx_malloc(sdata_len); /* get a buffer for it */ if(!sdata) return CURLE_OUT_OF_MEMORY; @@ -718,7 +728,7 @@ CURLcode Curl_gtls_cache_session(struct Curl_cfilter *cf, if(quic_tp && quic_tp_len) { qtp_clone = Curl_memdup0((char *)quic_tp, quic_tp_len); if(!qtp_clone) { - free(sdata); + curlx_free(sdata); return CURLE_OUT_OF_MEMORY; } } @@ -748,10 +758,8 @@ int Curl_glts_get_ietf_proto(gnutls_session_t session) return CURL_IETF_PROTO_TLS1_1; case GNUTLS_TLS1_2: return CURL_IETF_PROTO_TLS1_2; -#if GNUTLS_VERSION_NUMBER >= 0x030603 case GNUTLS_TLS1_3: return CURL_IETF_PROTO_TLS1_3; -#endif default: return CURL_IETF_PROTO_UNKNOWN; } @@ -825,7 +833,7 @@ static CURLcode gtls_set_priority(struct Curl_cfilter *cf, if((conn_config->cipher_list[0] == '+') || (conn_config->cipher_list[0] == '-') || (conn_config->cipher_list[0] == '!')) { - /* add it to out own */ + /* add it to out own */ if(!curlx_dyn_len(&buf)) { /* not added yet */ result = curlx_dyn_add(&buf, priority); if(result) @@ -862,20 +870,15 @@ static CURLcode gtls_client_init(struct Curl_cfilter *cf, struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); unsigned int init_flags; int rc; - bool sni = TRUE; /* default is SNI enabled */ const char *prioritylist; bool tls13support; CURLcode result; - if(!gtls_inited) - gtls_init(); - - if(config->version == CURL_SSLVERSION_SSLv2) { - failf(data, "GnuTLS does not support SSLv2"); + if(config->version == CURL_SSLVERSION_SSLv2 || + config->version == CURL_SSLVERSION_SSLv3) { + failf(data, "GnuTLS does not support SSLv2 or SSLv3"); return CURLE_SSL_CONNECT_ERROR; } - else if(config->version == CURL_SSLVERSION_SSLv3) - sni = FALSE; /* SSLv3 has no SNI */ /* allocate a shared creds struct */ result = Curl_gtls_shared_creds_create(data, >ls->shared_creds); @@ -887,7 +890,12 @@ static CURLcode gtls_client_init(struct Curl_cfilter *cf, infof(data, "Using TLS-SRP username: %s", config->username); rc = gnutls_srp_allocate_client_credentials(>ls->srp_client_cred); - if(rc != GNUTLS_E_SUCCESS) { + if(rc == GNUTLS_E_UNIMPLEMENTED_FEATURE) { + failf(data, "GnuTLS: TLS-SRP support not built in: %s", + gnutls_strerror(rc)); + return CURLE_NOT_BUILT_IN; + } + else if(rc != GNUTLS_E_SUCCESS) { failf(data, "gnutls_srp_allocate_client_cred() failed: %s", gnutls_strerror(rc)); return CURLE_OUT_OF_MEMORY; @@ -942,7 +950,7 @@ static CURLcode gtls_client_init(struct Curl_cfilter *cf, return CURLE_SSL_CONNECT_ERROR; } - if(sni && peer->sni) { + if(peer->sni) { if(gnutls_server_name_set(gtls->session, GNUTLS_NAME_DNS, peer->sni, strlen(peer->sni)) < 0) { failf(data, "Failed to set SNI"); @@ -958,16 +966,6 @@ static CURLcode gtls_client_init(struct Curl_cfilter *cf, /* "In GnuTLS 3.6.5, TLS 1.3 is enabled by default" */ tls13support = !!gnutls_check_version("3.6.5"); - /* Ensure +SRP comes at the *end* of all relevant strings so that it can be - * removed if a runtime error indicates that SRP is not supported by this - * GnuTLS version */ - - if(config->version == CURL_SSLVERSION_SSLv2 || - config->version == CURL_SSLVERSION_SSLv3) { - failf(data, "GnuTLS does not support SSLv2 or SSLv3"); - return CURLE_SSL_CONNECT_ERROR; - } - if(config->version == CURL_SSLVERSION_TLSv1_3) { if(!tls13support) { failf(data, "This GnuTLS installation does not support TLS 1.3"); @@ -1102,8 +1100,8 @@ static CURLcode gtls_on_session_reuse(struct Curl_cfilter *cf, connssl->earlydata_state = ssl_earlydata_await; connssl->state = ssl_connection_deferred; result = Curl_alpn_set_negotiated(cf, data, connssl, - (const unsigned char *)scs->alpn, - scs->alpn ? strlen(scs->alpn) : 0); + (const unsigned char *)scs->alpn, + scs->alpn ? strlen(scs->alpn) : 0); *do_early_data = !result; } return result; @@ -1136,7 +1134,7 @@ CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx, /* This might be a reconnect, so we check for a session ID in the cache to speed up things. We need to do this before constructing the gnutls session since we need to set flags depending on the kind of reuse. */ - if(conn_config->cache_session) { + if(conn_config->cache_session && !conn_config->verifystatus) { result = Curl_ssl_scache_take(cf, data, peer->scache_key, &scs); if(result) goto out; @@ -1161,7 +1159,7 @@ CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx, if(sess_reuse_cb) { result = sess_reuse_cb(cf, data, &alpns, scs, &do_early_data); if(result) - goto out; + goto out; } if(do_early_data) { /* We only try the ALPN protocol the session used before, @@ -1221,8 +1219,8 @@ CURLcode Curl_gtls_ctx_init(struct gtls_ctx *gctx, return result; } -static CURLcode -gtls_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) +static CURLcode gtls_connect_step1(struct Curl_cfilter *cf, + struct Curl_easy *data) { struct ssl_connect_data *connssl = cf->ctx; struct gtls_ssl_backend_data *backend = @@ -1292,8 +1290,10 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, do { int ret; - /* Begin Gyrations to get the public key */ - gnutls_pubkey_init(&key); + /* Begin Gyrations to get the public key */ + ret = gnutls_pubkey_init(&key); + if(ret < 0) + break; /* failed */ ret = gnutls_pubkey_import_x509(key, cert, 0); if(ret < 0) @@ -1303,7 +1303,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER || len1 == 0) break; /* failed */ - buff1 = malloc(len1); + buff1 = curlx_malloc(len1); if(!buff1) break; /* failed */ @@ -1327,8 +1327,7 @@ static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data, return result; } -void Curl_gtls_report_handshake(struct Curl_easy *data, - struct gtls_ctx *gctx) +void Curl_gtls_report_handshake(struct Curl_easy *data, struct gtls_ctx *gctx) { #ifndef CURL_DISABLE_VERBOSE_STRINGS if(Curl_trc_is_verbose(data)) { @@ -1452,7 +1451,12 @@ static CURLcode gtls_verify_ocsp_status(struct Curl_easy *data, goto out; } - gnutls_ocsp_resp_init(&ocsp_resp); + rc = gnutls_ocsp_resp_init(&ocsp_resp); + if(rc < 0) { + failf(data, "Failed to initialize OCSP response object"); + result = CURLE_SSL_INVALIDCERTSTATUS; + goto out; + } rc = gnutls_ocsp_resp_import(ocsp_resp, &status_request); if(rc < 0) { @@ -1569,8 +1573,7 @@ static CURLcode glts_apple_verify(struct Curl_cfilter *cf, CURLcode result; result = Curl_vtls_apple_verify(cf, data, peer, chain->num_certs, - gtls_chain_get_der, chain, - NULL, 0); + gtls_chain_get_der, chain, NULL, 0); *pverified = !result; if(*pverified) infof(data, " SSL certificate verified by Apple SecTrust."); @@ -1578,14 +1581,13 @@ static CURLcode glts_apple_verify(struct Curl_cfilter *cf, } #endif /* USE_APPLE_SECTRUST */ -CURLcode -Curl_gtls_verifyserver(struct Curl_cfilter *cf, - struct Curl_easy *data, - gnutls_session_t session, - struct ssl_primary_config *config, - struct ssl_config_data *ssl_config, - struct ssl_peer *peer, - const char *pinned_key) +CURLcode Curl_gtls_verifyserver(struct Curl_cfilter *cf, + struct Curl_easy *data, + gnutls_session_t session, + struct ssl_primary_config *config, + struct ssl_config_data *ssl_config, + struct ssl_peer *peer, + const char *pinned_key) { struct gtls_cert_chain chain; gnutls_x509_crt_t x509_cert = NULL, x509_issuer = NULL; @@ -1626,19 +1628,27 @@ Curl_gtls_verifyserver(struct Curl_cfilter *cf, } if(data->set.ssl.certinfo && chain.certs) { - unsigned int i; - - result = Curl_ssl_init_certinfo(data, (int)chain.num_certs); - if(result) + if(chain.num_certs > MAX_ALLOWED_CERT_AMOUNT) { + failf(data, "%u certificates is more than allowed (%u)", + chain.num_certs, MAX_ALLOWED_CERT_AMOUNT); + result = CURLE_SSL_CONNECT_ERROR; goto out; + } + else { + unsigned int i; - for(i = 0; i < chain.num_certs; i++) { - const char *beg = (const char *) chain.certs[i].data; - const char *end = beg + chain.certs[i].size; - - result = Curl_extract_certinfo(data, (int)i, beg, end); + result = Curl_ssl_init_certinfo(data, (int)chain.num_certs); if(result) goto out; + + for(i = 0; i < chain.num_certs; i++) { + const char *beg = (const char *)chain.certs[i].data; + const char *end = beg + chain.certs[i].size; + + result = Curl_extract_certinfo(data, (int)i, beg, end); + if(result) + goto out; + } } } @@ -1665,8 +1675,7 @@ Curl_gtls_verifyserver(struct Curl_cfilter *cf, infof(data, " SSL certificate verified by GnuTLS"); #ifdef USE_APPLE_SECTRUST - if(!verified && ssl_config->native_ca_store && - (verify_status & GNUTLS_CERT_SIGNER_NOT_FOUND)) { + if(!verified && ssl_config->native_ca_store) { result = glts_apple_verify(cf, data, peer, &chain, &verified); if(result && (result != CURLE_PEER_FAILED_VERIFICATION)) goto out; /* unexpected error */ @@ -1817,51 +1826,8 @@ Curl_gtls_verifyserver(struct Curl_cfilter *cf, rc = (int)gnutls_x509_crt_check_hostname(x509_cert, peer->sni ? peer->sni : peer->hostname); -#if GNUTLS_VERSION_NUMBER < 0x030306 - /* Before 3.3.6, gnutls_x509_crt_check_hostname() did not check IP - addresses. */ - if(!rc) { -#ifdef USE_IPV6 - #define use_addr in6_addr -#else - #define use_addr in_addr -#endif - unsigned char addrbuf[sizeof(struct use_addr)]; - size_t addrlen = 0; - - if(curlx_inet_pton(AF_INET, peer->hostname, addrbuf) > 0) - addrlen = 4; -#ifdef USE_IPV6 - else if(curlx_inet_pton(AF_INET6, peer->hostname, addrbuf) > 0) - addrlen = 16; -#endif - - if(addrlen) { - unsigned char certaddr[sizeof(struct use_addr)]; - int i; - - for(i = 0; ; i++) { - size_t certaddrlen = sizeof(certaddr); - int ret = gnutls_x509_crt_get_subject_alt_name(x509_cert, i, certaddr, - &certaddrlen, NULL); - /* If this happens, it was not an IP address. */ - if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER) - continue; - if(ret < 0) - break; - if(ret != GNUTLS_SAN_IPADDRESS) - continue; - if(certaddrlen == addrlen && !memcmp(addrbuf, certaddr, addrlen)) { - rc = 1; - break; - } - } - } - } -#endif - result = (!rc && config->verifyhost) ? - CURLE_PEER_FAILED_VERIFICATION : CURLE_OK; + CURLE_PEER_FAILED_VERIFICATION : CURLE_OK; gtls_msg_verify_result(data, peer, x509_cert, rc, config->verifyhost); if(result) goto out; @@ -1922,7 +1888,7 @@ static CURLcode gtls_send_earlydata(struct Curl_cfilter *cf, { struct ssl_connect_data *connssl = cf->ctx; struct gtls_ssl_backend_data *backend = - (struct gtls_ssl_backend_data *)connssl->backend; + (struct gtls_ssl_backend_data *)connssl->backend; CURLcode result = CURLE_OK; const unsigned char *buf; size_t blen; @@ -1932,8 +1898,7 @@ static CURLcode gtls_send_earlydata(struct Curl_cfilter *cf, backend->gtls.io_result = CURLE_OK; while(Curl_bufq_peek(&connssl->earlydata, &buf, &blen)) { n = gnutls_record_send_early_data(backend->gtls.session, buf, blen); - CURL_TRC_CF(data, cf, "gtls_send_earlydata(len=%zu) -> %zd", - blen, n); + CURL_TRC_CF(data, cf, "gtls_send_earlydata(len=%zu) -> %zd", blen, n); if(n < 0) { if(n == GNUTLS_E_AGAIN) result = CURLE_AGAIN; @@ -1968,10 +1933,11 @@ static CURLcode gtls_send_earlydata(struct Curl_cfilter *cf, */ static CURLcode gtls_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data, - bool *done) { + bool *done) +{ struct ssl_connect_data *connssl = cf->ctx; struct gtls_ssl_backend_data *backend = - (struct gtls_ssl_backend_data *)connssl->backend; + (struct gtls_ssl_backend_data *)connssl->backend; CURLcode result = CURLE_OK; DEBUGASSERT(backend); @@ -2005,7 +1971,7 @@ static CURLcode gtls_connect_common(struct Curl_cfilter *cf, DEBUGASSERT((connssl->earlydata_state == ssl_earlydata_none) || (connssl->earlydata_state == ssl_earlydata_sent)); #endif - result = handshake(cf, data); + result = cf_gtls_handshake(cf, data); if(result) goto out; connssl->connecting_state = ssl_connect_3; @@ -2155,7 +2121,7 @@ static CURLcode gtls_shutdown(struct Curl_cfilter *cf, size_t i; DEBUGASSERT(backend); - /* If we have no handshaked connection or already shut down */ + /* If we have no handshaked connection or already shut down */ if(!backend->gtls.session || cf->shutdown || connssl->state != ssl_connection_complete) { *done = TRUE; @@ -2265,11 +2231,10 @@ static CURLcode gtls_recv(struct Curl_cfilter *cf, goto out; } else if(nread == GNUTLS_E_REHANDSHAKE) { - /* BLOCKING call, this is bad but a work-around for now. Fixing this "the - proper way" takes a whole lot of work. */ - result = handshake(cf, data); + /* Either TLSv1.2 renegotiate or a TLSv1.3 session key update. */ + result = cf_gtls_handshake(cf, data); if(!result) - result = CURLE_AGAIN; /* then return as if this was a wouldblock */ + result = CURLE_AGAIN; /* make us get called again. */ goto out; } else { @@ -2335,6 +2300,7 @@ const struct Curl_ssl Curl_ssl_gnutls = { SSLSUPP_CERTINFO | SSLSUPP_PINNEDPUBKEY | SSLSUPP_HTTPS_PROXY | + SSLSUPP_CAINFO_BLOB | SSLSUPP_CIPHER_LIST | SSLSUPP_CA_CACHE, diff --git a/lib/vtls/gtls.h b/lib/vtls/gtls.h index afbe51eb9cb8..4ed79f63ed39 100644 --- a/lib/vtls/gtls.h +++ b/lib/vtls/gtls.h @@ -25,7 +25,6 @@ ***************************************************************************/ #include "../curl_setup.h" -#include #ifdef USE_GNUTLS @@ -119,8 +118,7 @@ CURLcode Curl_gtls_cache_session(struct Curl_cfilter *cf, size_t quic_tp_len); /* Report properties of a successful handshake */ -void Curl_gtls_report_handshake(struct Curl_easy *data, - struct gtls_ctx *gctx); +void Curl_gtls_report_handshake(struct Curl_easy *data, struct gtls_ctx *gctx); extern const struct Curl_ssl Curl_ssl_gnutls; diff --git a/lib/vtls/hostcheck.c b/lib/vtls/hostcheck.c index 23ba33951f17..e56860a35ba9 100644 --- a/lib/vtls/hostcheck.c +++ b/lib/vtls/hostcheck.c @@ -37,10 +37,6 @@ #include "hostcheck.h" #include "../hostip.h" -#include "../curl_memory.h" -/* The last #include file should be: */ -#include "../memdebug.h" - /* check the two input strings with given length, but do not assume they end in nul-bytes */ static bool pmatch(const char *hostname, size_t hostlen, @@ -88,16 +84,16 @@ static bool hostmatch(const char *hostname, DEBUGASSERT(hostlen); /* normalize pattern and hostname by stripping off trailing dots */ - if(hostname[hostlen-1]=='.') + if(hostname[hostlen - 1] == '.') hostlen--; - if(pattern[patternlen-1]=='.') + if(pattern[patternlen - 1] == '.') patternlen--; if(strncmp(pattern, "*.", 2)) return pmatch(hostname, hostlen, pattern, patternlen); - /* detect IP address as hostname and fail the match if so */ - else if(Curl_host_is_ipnum(hostname)) + /* detect host as IP address or starting with a dot and fail if so */ + else if(Curl_host_is_ipnum(hostname) || (hostname[0] == '.')) return FALSE; /* We require at least 2 dots in the pattern to avoid too wide wildcard diff --git a/lib/vtls/hostcheck.h b/lib/vtls/hostcheck.h index b843d09c65ed..ca767be3ce1d 100644 --- a/lib/vtls/hostcheck.h +++ b/lib/vtls/hostcheck.h @@ -24,7 +24,7 @@ * ***************************************************************************/ -#include +#include "../curl_setup.h" #if defined(USE_OPENSSL) || defined(USE_SCHANNEL) diff --git a/lib/vtls/keylog.c b/lib/vtls/keylog.c index 9179d38fe76f..2c1c595bfc98 100644 --- a/lib/vtls/keylog.c +++ b/lib/vtls/keylog.c @@ -31,19 +31,13 @@ defined(USE_RUSTLS) #include "keylog.h" -#include #include "../escape.h" #include "../curlx/fopen.h" -/* The last #include files should be: */ -#include "../curl_memory.h" -#include "../memdebug.h" - /* The fp for the open SSLKEYLOGFILE, or NULL if not open */ static FILE *keylog_file_fp; -void -Curl_tls_keylog_open(void) +void Curl_tls_keylog_open(void) { char *keylog_file_name; @@ -67,8 +61,7 @@ Curl_tls_keylog_open(void) } } -void -Curl_tls_keylog_close(void) +void Curl_tls_keylog_close(void) { if(keylog_file_fp) { curlx_fclose(keylog_file_fp); @@ -76,14 +69,12 @@ Curl_tls_keylog_close(void) } } -bool -Curl_tls_keylog_enabled(void) +bool Curl_tls_keylog_enabled(void) { return keylog_file_fp != NULL; } -bool -Curl_tls_keylog_write_line(const char *line) +bool Curl_tls_keylog_write_line(const char *line) { /* The current maximum valid keylog line length LF and NUL is 195. */ size_t linelen; @@ -111,10 +102,9 @@ Curl_tls_keylog_write_line(const char *line) return TRUE; } -bool -Curl_tls_keylog_write(const char *label, - const unsigned char client_random[CLIENT_RANDOM_SIZE], - const unsigned char *secret, size_t secretlen) +bool Curl_tls_keylog_write(const char *label, + const unsigned char client_random[CLIENT_RANDOM_SIZE], + const unsigned char *secret, size_t secretlen) { size_t pos, i; unsigned char line[KEYLOG_LABEL_MAXLEN + 1 + 2 * CLIENT_RANDOM_SIZE + 1 + diff --git a/lib/vtls/mbedtls.c b/lib/vtls/mbedtls.c index 3ff131b441a0..46bfa0967e55 100644 --- a/lib/vtls/mbedtls.c +++ b/lib/vtls/mbedtls.c @@ -38,47 +38,44 @@ #include #if MBEDTLS_VERSION_NUMBER < 0x03020000 - #error "mbedTLS 3.2.0 or later required" +#error "mbedTLS 3.2.0 or later required" #endif +#include #include #include #include +#include + +#if MBEDTLS_VERSION_NUMBER < 0x04000000 && !defined(MBEDTLS_CTR_DRBG_C) +#error "MBEDTLS_CTR_DRBG_C is required for mbedTLS 3.x." +#endif #include +#if MBEDTLS_VERSION_NUMBER < 0x04000000 #include #include -#include +#endif #ifdef MBEDTLS_DEBUG #include #endif #include "cipher_suite.h" #include "../urldata.h" -#include "../sendf.h" -#include "../curlx/inet_pton.h" +#include "../curl_trc.h" #include "mbedtls.h" #include "vtls.h" #include "vtls_int.h" #include "vtls_scache.h" #include "x509asn1.h" -#include "../parsedate.h" #include "../connect.h" /* for the connect timeout */ -#include "../select.h" -#include "../multiif.h" -#include "mbedtls_threadlock.h" #include "../strdup.h" - -/* The last 2 #include files should be in this order */ -#include "../curl_memory.h" -#include "../memdebug.h" +#include "../curl_sha256.h" /* ALPN for http2 */ #if defined(USE_HTTP2) && defined(MBEDTLS_SSL_ALPN) -# define HAS_ALPN_MBEDTLS +#define HAS_ALPN_MBEDTLS #endif struct mbed_ssl_backend_data { - mbedtls_ctr_drbg_context ctr_drbg; - mbedtls_entropy_context entropy; mbedtls_ssl_context ssl; mbedtls_x509_crt cacert; mbedtls_x509_crt clicert; @@ -97,55 +94,21 @@ struct mbed_ssl_backend_data { BIT(send_blocked); }; -/* apply threading? */ -#if (defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || defined(_WIN32) -#define HAS_THREADING_SUPPORT +/** A context for random number generation (RNG). + */ +#if MBEDTLS_VERSION_NUMBER < 0x04000000 +struct rng_context_t { + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context drbg; +}; + +static struct rng_context_t rng; #endif #ifndef MBEDTLS_ERROR_C -#define mbedtls_strerror(a,b,c) b[0] = 0 +#define mbedtls_strerror(a, b, c) b[0] = 0 #endif -#ifdef HAS_THREADING_SUPPORT -static mbedtls_entropy_context ts_entropy; - -static int entropy_init_initialized = 0; - -static void entropy_init_mutex(mbedtls_entropy_context *ctx) -{ - /* lock 0 = entropy_init_mutex() */ - Curl_mbedtlsthreadlock_lock_function(0); - if(entropy_init_initialized == 0) { - mbedtls_entropy_init(ctx); - entropy_init_initialized = 1; - } - Curl_mbedtlsthreadlock_unlock_function(0); -} - -static void entropy_cleanup_mutex(mbedtls_entropy_context *ctx) -{ - /* lock 0 = use same lock as init */ - Curl_mbedtlsthreadlock_lock_function(0); - if(entropy_init_initialized == 1) { - mbedtls_entropy_free(ctx); - entropy_init_initialized = 0; - } - Curl_mbedtlsthreadlock_unlock_function(0); -} - -static int entropy_func_mutex(void *data, unsigned char *output, size_t len) -{ - int ret; - /* lock 1 = entropy_func_mutex() */ - Curl_mbedtlsthreadlock_lock_function(1); - ret = mbedtls_entropy_func(data, output, len); - Curl_mbedtlsthreadlock_unlock_function(1); - - return ret; -} - -#endif /* HAS_THREADING_SUPPORT */ - #ifdef MBEDTLS_DEBUG static void mbed_debug(void *context, int level, const char *f_name, int line_nb, const char *line) @@ -177,8 +140,7 @@ static int mbedtls_bio_cf_write(void *bio, if(!data) return 0; - result = Curl_conn_cf_send(cf->next, data, (const char *)buf, blen, FALSE, - &nwritten); + result = Curl_conn_cf_send(cf->next, data, buf, blen, FALSE, &nwritten); CURL_TRC_CF(data, cf, "mbedtls_bio_cf_out_write(len=%zu) -> %d, %zu", blen, result, nwritten); if(CURLE_AGAIN == result) @@ -190,7 +152,7 @@ static int mbedtls_bio_cf_read(void *bio, unsigned char *buf, size_t blen) { struct Curl_cfilter *cf = bio; struct Curl_easy *data = CF_DATA_CURRENT(cf); - size_t nread; + size_t nread = 0; CURLcode result; DEBUGASSERT(data); @@ -205,29 +167,13 @@ static int mbedtls_bio_cf_read(void *bio, unsigned char *buf, size_t blen) blen, result, nread); if(CURLE_AGAIN == result) return MBEDTLS_ERR_SSL_WANT_READ; + /* nread is never larger than int here */ return result ? -1 : (int)nread; } -/* - * profile +/* See: + * https://web.archive.org/web/20200921194007/tls.mbed.org/discussions/generic/howto-determine-exact-buffer-len-for-mbedtls_pk_write_pubkey_der */ -static const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr = -{ - /* Hashes from SHA-1 and above */ - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_RIPEMD160) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA224) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | - MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512), - 0xFFFFFFF, /* Any PK alg */ - 0xFFFFFFF, /* Any curve */ - 1024, /* RSA min key len */ -}; - -/* See https://web.archive.org/web/20200921194007/tls.mbed.org/discussions/ - generic/howto-determine-exact-buffer-len-for-mbedtls_pk_write_pubkey_der -*/ #define RSA_PUB_DER_MAX_BYTES (38 + 2 * MBEDTLS_MPI_MAX_SIZE) #define ECP_PUB_DER_MAX_BYTES (30 + 2 * MBEDTLS_ECP_MAX_BYTES) @@ -239,12 +185,13 @@ mbed_set_ssl_version_min_max(struct Curl_easy *data, struct mbed_ssl_backend_data *backend, struct ssl_primary_config *conn_config) { - /* TLS 1.0 and TLS 1.1 were dropped with mbedTLS 3.0.0 (2021). So, since - * then, and before the introduction of TLS 1.3 in 3.6.0 (2024), this - * function basically always sets TLS 1.2 as min/max, unless given - * unsupported option values. */ - - mbedtls_ssl_protocol_version ver_min = MBEDTLS_SSL_VERSION_TLS1_2; + mbedtls_ssl_protocol_version ver_min = +#ifdef MBEDTLS_SSL_PROTO_TLS1_2 + MBEDTLS_SSL_VERSION_TLS1_2 +#else + MBEDTLS_SSL_VERSION_TLS1_3 +#endif + ; mbedtls_ssl_protocol_version ver_max = #ifdef MBEDTLS_SSL_PROTO_TLS1_3 MBEDTLS_SSL_VERSION_TLS1_3 @@ -259,8 +206,10 @@ mbed_set_ssl_version_min_max(struct Curl_easy *data, case CURL_SSLVERSION_TLSv1_0: case CURL_SSLVERSION_TLSv1_1: case CURL_SSLVERSION_TLSv1_2: +#ifdef MBEDTLS_SSL_PROTO_TLS1_2 ver_min = MBEDTLS_SSL_VERSION_TLS1_2; break; +#endif case CURL_SSLVERSION_TLSv1_3: #ifdef MBEDTLS_SSL_PROTO_TLS1_3 ver_min = MBEDTLS_SSL_VERSION_TLS1_3; @@ -280,9 +229,11 @@ mbed_set_ssl_version_min_max(struct Curl_easy *data, ver_max = MBEDTLS_SSL_VERSION_TLS1_3; break; #endif +#ifdef MBEDTLS_SSL_PROTO_TLS1_2 case CURL_SSLVERSION_MAX_TLSv1_2: ver_max = MBEDTLS_SSL_VERSION_TLS1_2; break; +#endif case CURL_SSLVERSION_MAX_TLSv1_1: case CURL_SSLVERSION_MAX_TLSv1_0: default: @@ -301,9 +252,8 @@ mbed_set_ssl_version_min_max(struct Curl_easy *data, cipher suite present in other SSL implementations. Provide provisional support for specifying the cipher suite here. */ #ifdef MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 -static int -mbed_cipher_suite_get_str(uint16_t id, char *buf, size_t buf_size, - bool prefer_rfc) +static int mbed_cipher_suite_get_str(uint16_t id, char *buf, size_t buf_size, + bool prefer_rfc) { if(id == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8) curl_msnprintf(buf, buf_size, "%s", "TLS_ECJPAKE_WITH_AES_128_CCM_8"); @@ -312,8 +262,7 @@ mbed_cipher_suite_get_str(uint16_t id, char *buf, size_t buf_size, return 0; } -static uint16_t -mbed_cipher_suite_walk_str(const char **str, const char **end) +static uint16_t mbed_cipher_suite_walk_str(const char **str, const char **end) { uint16_t id = Curl_cipher_suite_walk_str(str, end); size_t len = *end - *str; @@ -342,10 +291,11 @@ mbed_set_selected_ciphers(struct Curl_easy *data, const char *ptr, *end; supported = mbedtls_ssl_list_ciphersuites(); - for(i = 0; supported[i] != 0; i++); + for(i = 0; supported[i] != 0; i++) + ; supported_len = i; - selected = malloc(sizeof(int) * (supported_len + 1)); + selected = curlx_malloc(sizeof(int) * (supported_len + 1)); if(!selected) return CURLE_OUT_OF_MEMORY; @@ -355,7 +305,7 @@ mbed_set_selected_ciphers(struct Curl_easy *data, if(!ciphers13) { /* Add default TLSv1.3 ciphers to selection */ for(j = 0; j < supported_len; j++) { - uint16_t id = (uint16_t) supported[j]; + uint16_t id = (uint16_t)supported[j]; if(strncmp(mbedtls_ssl_get_ciphersuite_name(id), "TLS1-3", 6) != 0) continue; @@ -374,23 +324,25 @@ mbed_set_selected_ciphers(struct Curl_easy *data, /* Check if cipher is supported */ if(id) { - for(i = 0; i < supported_len && supported[i] != id; i++); + for(i = 0; i < supported_len && supported[i] != id; i++) + ; if(i == supported_len) id = 0; } if(!id) { if(ptr[0] != '\0') infof(data, "mbedTLS: unknown cipher in list: \"%.*s\"", - (int) (end - ptr), ptr); + (int)(end - ptr), ptr); continue; } /* No duplicates allowed (so selected cannot overflow) */ - for(i = 0; i < count && selected[i] != id; i++); + for(i = 0; i < count && selected[i] != id; i++) + ; if(i < count) { if(i >= default13_count) infof(data, "mbedTLS: duplicate cipher in list: \"%.*s\"", - (int) (end - ptr), ptr); + (int)(end - ptr), ptr); continue; } @@ -406,12 +358,13 @@ mbed_set_selected_ciphers(struct Curl_easy *data, if(!ciphers12) { /* Add default TLSv1.2 ciphers to selection */ for(j = 0; j < supported_len; j++) { - uint16_t id = (uint16_t) supported[j]; + uint16_t id = (uint16_t)supported[j]; if(strncmp(mbedtls_ssl_get_ciphersuite_name(id), "TLS1-3", 6) == 0) continue; /* No duplicates allowed (so selected cannot overflow) */ - for(i = 0; i < count && selected[i] != id; i++); + for(i = 0; i < count && selected[i] != id; i++) + ; if(i < count) continue; @@ -423,7 +376,7 @@ mbed_set_selected_ciphers(struct Curl_easy *data, selected[count] = 0; if(count == 0) { - free(selected); + curlx_free(selected); failf(data, "mbedTLS: no supported cipher in list"); return CURLE_SSL_CIPHER; } @@ -435,42 +388,51 @@ mbed_set_selected_ciphers(struct Curl_easy *data, return CURLE_OK; } -static void -mbed_dump_cert_info(struct Curl_easy *data, const mbedtls_x509_crt *crt) +static void mbed_dump_cert_info(struct Curl_easy *data, + const mbedtls_x509_crt *crt) { #if defined(CURL_DISABLE_VERBOSE_STRINGS) || defined(MBEDTLS_X509_REMOVE_INFO) (void)data, (void)crt; #else const size_t bufsize = 16384; - char *p, *buffer = malloc(bufsize); + char *p, *buffer = curlx_malloc(bufsize); if(buffer && mbedtls_x509_crt_info(buffer, bufsize, " ", crt) > 0) { infof(data, "Server certificate:"); for(p = buffer; *p; p += *p != '\0') { size_t s = strcspn(p, "\n"); - infof(data, "%.*s", (int) s, p); + infof(data, "%.*s", (int)s, p); p += s; } } else infof(data, "Unable to dump certificate information"); - free(buffer); + curlx_free(buffer); #endif } -static void -mbed_extract_certinfo(struct Curl_easy *data, const mbedtls_x509_crt *crt) +static void mbed_extract_certinfo(struct Curl_easy *data, + const mbedtls_x509_crt *crt) { CURLcode result; const mbedtls_x509_crt *cur; + int cert_count = 0; int i; - for(i = 0, cur = crt; cur; ++i, cur = cur->next); - result = Curl_ssl_init_certinfo(data, i); + for(cur = crt; cur && cert_count <= MAX_ALLOWED_CERT_AMOUNT; cur = cur->next) + cert_count++; + + if(cert_count > MAX_ALLOWED_CERT_AMOUNT) { + infof(data, "Certificates is more than allowed (%u), skipping certinfo", + MAX_ALLOWED_CERT_AMOUNT); + return; + } + + result = Curl_ssl_init_certinfo(data, cert_count); for(i = 0, cur = crt; result == CURLE_OK && cur; ++i, cur = cur->next) { - const char *beg = (const char *) cur->raw.p; + const char *beg = (const char *)cur->raw.p; const char *end = beg + cur->raw.len; result = Curl_extract_certinfo(data, i, beg, end); } @@ -479,7 +441,7 @@ mbed_extract_certinfo(struct Curl_easy *data, const mbedtls_x509_crt *crt) static int mbed_verify_cb(void *ptr, mbedtls_x509_crt *crt, int depth, uint32_t *flags) { - struct Curl_cfilter *cf = (struct Curl_cfilter *) ptr; + struct Curl_cfilter *cf = (struct Curl_cfilter *)ptr; struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); struct Curl_easy *data = CF_DATA_CURRENT(cf); @@ -508,8 +470,8 @@ static int mbed_verify_cb(void *ptr, mbedtls_x509_crt *crt, return 0; } -static CURLcode -mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) +static CURLcode mbed_connect_step1(struct Curl_cfilter *cf, + struct Curl_easy *data) { struct ssl_connect_data *connssl = cf->ctx; struct mbed_ssl_backend_data *backend = @@ -524,6 +486,9 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) const char * const ssl_capath = conn_config->CApath; char * const ssl_cert = ssl_config->primary.clientcert; const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob; +#ifdef MBEDTLS_PEM_PARSE_C + const char * const ssl_cert_type = ssl_config->cert_type; +#endif const char * const ssl_crlfile = ssl_config->primary.CRLfile; const char *hostname = connssl->peer.hostname; int ret = -1; @@ -538,48 +503,49 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) return CURLE_NOT_BUILT_IN; } -#ifdef HAS_THREADING_SUPPORT - mbedtls_ctr_drbg_init(&backend->ctr_drbg); - - ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, entropy_func_mutex, - &ts_entropy, NULL, 0); - if(ret) { - mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); - failf(data, "mbedtls_ctr_drbg_seed returned (-0x%04X) %s", - -ret, errorbuf); - return CURLE_FAILED_INIT; - } -#else - mbedtls_entropy_init(&backend->entropy); - mbedtls_ctr_drbg_init(&backend->ctr_drbg); - - ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, mbedtls_entropy_func, - &backend->entropy, NULL, 0); - if(ret) { - mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); - failf(data, "mbedtls_ctr_drbg_seed returned (-0x%04X) %s", - -ret, errorbuf); - return CURLE_FAILED_INIT; - } -#endif /* HAS_THREADING_SUPPORT */ - /* Load the trusted CA */ mbedtls_x509_crt_init(&backend->cacert); if(ca_info_blob && verifypeer) { - /* 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 = Curl_memdup0(ca_info_blob->data, - ca_info_blob->len); - if(!newblob) - return CURLE_OUT_OF_MEMORY; - ret = mbedtls_x509_crt_parse(&backend->cacert, newblob, - ca_info_blob->len + 1); - free(newblob); +#ifdef MBEDTLS_PEM_PARSE_C + /* if DER or a null-terminated PEM just process using + mbedtls_x509_crt_parse(). */ + if((ssl_cert_type && curl_strequal(ssl_cert_type, "DER")) || + ((char *)(ca_info_blob->data))[ca_info_blob->len - 1] == '\0') { + + ret = mbedtls_x509_crt_parse(&backend->cacert, + ca_info_blob->data, + ca_info_blob->len); + } + else { /* they say it is PEM and it is not null-terminated */ + + /* Unfortunately, mbedtls_x509_crt_parse() requires the data to + be null-terminated if the data is PEM encoded (even when + provided the exact length). The function accepts PEM or DER + formats, but we cannot assume if the user passed in a PEM + format cert that it is null-terminated. */ + unsigned char *newblob = Curl_memdup0(ca_info_blob->data, + ca_info_blob->len); + if(!newblob) + return CURLE_OUT_OF_MEMORY; + + ret = mbedtls_x509_crt_parse(&backend->cacert, newblob, + ca_info_blob->len + 1); + curlx_free(newblob); + } +#else + /* DER encoded certs do not need to be null terminated + because it is a binary format. So if we are not compiling + with PEM_PARSE we can avoid the extra memory copies + altogether. */ + ret = mbedtls_x509_crt_parse_der(&backend->cacert, + ca_info_blob->data, + ca_info_blob->len); +#endif + if(ret < 0) { mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); - failf(data, "Error importing ca cert blob - mbedTLS: (-0x%04X) %s", + failf(data, "mbedTLS: error importing CA cert blob: (-0x%04X) %s", -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } @@ -591,12 +557,12 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) if(ret < 0) { mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); - failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s", + failf(data, "mbedTLS: error reading CA cert file %s: (-0x%04X) %s", ssl_cafile, -ret, errorbuf); return CURLE_SSL_CACERT_BADFILE; } #else - failf(data, "mbedtls: functions that use the file system not built in"); + failf(data, "mbedTLS: functions that use the file system not built in"); return CURLE_NOT_BUILT_IN; #endif } @@ -607,14 +573,14 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) if(ret < 0) { mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); - failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s", + failf(data, "mbedTLS: error reading CA cert path %s: (-0x%04X) %s", ssl_capath, -ret, errorbuf); if(verifypeer) return CURLE_SSL_CACERT_BADFILE; } #else - failf(data, "mbedtls: functions that use the file system not built in"); + failf(data, "mbedTLS: functions that use the file system not built in"); return CURLE_NOT_BUILT_IN; #endif } @@ -628,32 +594,56 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) if(ret) { mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); - failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s", + failf(data, "mbedTLS: error reading client cert file %s: (-0x%04X) %s", ssl_cert, -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } #else - failf(data, "mbedtls: functions that use the file system not built in"); + failf(data, "mbedTLS: functions that use the file system not built in"); return CURLE_NOT_BUILT_IN; #endif } if(ssl_cert_blob) { - /* 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 = Curl_memdup0(ssl_cert_blob->data, - ssl_cert_blob->len); - if(!newblob) - return CURLE_OUT_OF_MEMORY; - ret = mbedtls_x509_crt_parse(&backend->clicert, newblob, - ssl_cert_blob->len + 1); - free(newblob); +#ifdef MBEDTLS_PEM_PARSE_C + /* if DER or a null-terminated PEM just process using + mbedtls_x509_crt_parse(). */ + if((ssl_cert_type && curl_strequal(ssl_cert_type, "DER")) || + ((char *)(ssl_cert_blob->data))[ssl_cert_blob->len - 1] == '\0') { + + ret = mbedtls_x509_crt_parse(&backend->clicert, + ssl_cert_blob->data, + ssl_cert_blob->len); + } + else { /* they say it is PEM and it is not null-terminated */ + + /* Unfortunately, mbedtls_x509_crt_parse() requires the data to + be null-terminated if the data is PEM encoded (even when + provided the exact length). The function accepts PEM or DER + formats, but we cannot assume if the user passed in a PEM + format cert that it is null-terminated. */ + unsigned char *newblob = Curl_memdup0(ssl_cert_blob->data, + ssl_cert_blob->len); + if(!newblob) + return CURLE_OUT_OF_MEMORY; + ret = mbedtls_x509_crt_parse(&backend->clicert, newblob, + ssl_cert_blob->len + 1); + curlx_free(newblob); + } +#else + /* DER encoded certs do not need to be null terminated + because it is a binary format. So if we are not compiling + with PEM_PARSE we can avoid the extra memory copies + altogether. */ + ret = mbedtls_x509_crt_parse_der(&backend->clicert, + ssl_cert_blob->data, + ssl_cert_blob->len); +#endif if(ret) { mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); - failf(data, "Error reading client cert data %s - mbedTLS: (-0x%04X) %s", + failf(data, "mbedTLS: error reading client cert data %s: (-0x%04X) %s", ssl_config->key, -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } @@ -665,22 +655,34 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) if(ssl_config->key || ssl_config->key_blob) { if(ssl_config->key) { #ifdef MBEDTLS_FS_IO +#if MBEDTLS_VERSION_NUMBER >= 0x04000000 + ret = mbedtls_pk_parse_keyfile(&backend->pk, ssl_config->key, + ssl_config->key_passwd); + if(ret == 0 && !(mbedtls_pk_can_do_psa(&backend->pk, + PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH), + PSA_KEY_USAGE_SIGN_HASH) || + mbedtls_pk_can_do_psa(&backend->pk, + MBEDTLS_PK_ALG_ECDSA(PSA_ALG_ANY_HASH), + PSA_KEY_USAGE_SIGN_HASH))) + ret = MBEDTLS_ERR_PK_TYPE_MISMATCH; +#else ret = mbedtls_pk_parse_keyfile(&backend->pk, ssl_config->key, ssl_config->key_passwd, mbedtls_ctr_drbg_random, - &backend->ctr_drbg); + &rng.drbg); if(ret == 0 && !(mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_RSA) || mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_ECKEY))) ret = MBEDTLS_ERR_PK_TYPE_MISMATCH; +#endif if(ret) { mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); - failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s", + failf(data, "mbedTLS: error reading private key %s: (-0x%04X) %s", ssl_config->key, -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } #else - failf(data, "mbedtls: functions that use the file system not built in"); + failf(data, "mbedTLS: functions that use the file system not built in"); return CURLE_NOT_BUILT_IN; #endif } @@ -689,18 +691,31 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) const unsigned char *key_data = (const unsigned char *)ssl_key_blob->data; const char *passwd = ssl_config->key_passwd; +#if MBEDTLS_VERSION_NUMBER >= 0x04000000 + ret = mbedtls_pk_parse_key(&backend->pk, key_data, ssl_key_blob->len, + (const unsigned char *)passwd, + passwd ? strlen(passwd) : 0); + if(ret == 0 && !(mbedtls_pk_can_do_psa(&backend->pk, + PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH), + PSA_KEY_USAGE_SIGN_HASH) || + mbedtls_pk_can_do_psa(&backend->pk, + MBEDTLS_PK_ALG_ECDSA(PSA_ALG_ANY_HASH), + PSA_KEY_USAGE_SIGN_HASH))) + ret = MBEDTLS_ERR_PK_TYPE_MISMATCH; +#else ret = mbedtls_pk_parse_key(&backend->pk, key_data, ssl_key_blob->len, (const unsigned char *)passwd, passwd ? strlen(passwd) : 0, mbedtls_ctr_drbg_random, - &backend->ctr_drbg); + &rng.drbg); if(ret == 0 && !(mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_RSA) || mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_ECKEY))) ret = MBEDTLS_ERR_PK_TYPE_MISMATCH; +#endif if(ret) { mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); - failf(data, "Error parsing private key - mbedTLS: (-0x%04X) %s", + failf(data, "mbedTLS: error parsing private key: (-0x%04X) %s", -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } @@ -717,19 +732,19 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) if(ret) { mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); - failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s", + failf(data, "mbedTLS: error reading CRL file %s: (-0x%04X) %s", ssl_crlfile, -ret, errorbuf); return CURLE_SSL_CRL_BADFILE; } #else - failf(data, "mbedtls: functions that use the file system not built in"); + failf(data, "mbedTLS: functions that use the file system not built in"); return CURLE_NOT_BUILT_IN; #endif } #else if(ssl_crlfile) { - failf(data, "mbedtls: crl support not built in"); + failf(data, "mbedTLS: CRL support not built in"); return CURLE_NOT_BUILT_IN; } #endif @@ -746,8 +761,22 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) return CURLE_SSL_CONNECT_ERROR; } -#ifdef MBEDTLS_SSL_SESSION_TICKETS - /* New in mbedTLS 3.6.1, need to enable, default is now disabled */ +#ifdef MBEDTLS_DEBUG + /* In order to make that work in mbedtls MBEDTLS_DEBUG_C must be defined. */ + mbedtls_ssl_conf_dbg(&backend->config, mbed_debug, data); + /* - 0 No debug + * - 1 Error + * - 2 State change + * - 3 Informational + * - 4 Verbose + */ + mbedtls_debug_set_threshold(4); +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \ + MBEDTLS_VERSION_NUMBER >= 0x03060100 && MBEDTLS_VERSION_NUMBER < 0x04000000 + /* New in mbedTLS 3.6.1, need to enable, default is now disabled. + 4.0.0 enabled it by default for TLSv1.3. */ mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets(&backend->config, MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED); #endif @@ -761,21 +790,23 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) mbedtls_ssl_init(&backend->ssl); backend->initialized = TRUE; - /* new profile with RSA min key len = 1024 ... */ + /* use the default secure profile baked into mbedTLS */ mbedtls_ssl_conf_cert_profile(&backend->config, - &mbedtls_x509_crt_profile_fr); + &mbedtls_x509_crt_profile_next); ret = mbed_set_ssl_version_min_max(data, backend, conn_config); if(ret != CURLE_OK) return ret; +#if MBEDTLS_VERSION_NUMBER < 0x04000000 mbedtls_ssl_conf_rng(&backend->config, mbedtls_ctr_drbg_random, - &backend->ctr_drbg); + &rng.drbg); +#endif ret = mbedtls_ssl_setup(&backend->ssl, &backend->config); if(ret) { mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); - failf(data, "ssl_setup failed - mbedTLS: (-0x%04X) %s", + failf(data, "mbedTLS: ssl_setup failed: (-0x%04X) %s", -ret, errorbuf); return CURLE_SSL_CONNECT_ERROR; } @@ -806,7 +837,6 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) mbedtls_ssl_list_ciphersuites()); } - #ifdef MBEDTLS_SSL_RENEGOTIATION mbedtls_ssl_conf_renegotiation(&backend->config, MBEDTLS_SSL_RENEGOTIATION_ENABLED); @@ -818,7 +848,7 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) #endif /* Check if there is a cached ID we can/should use here! */ - if(ssl_config->primary.cache_session) { + if(Curl_ssl_scache_use(cf, data)) { struct Curl_ssl_session *sc_session = NULL; CURLcode result; @@ -887,18 +917,6 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) } #endif -#ifdef MBEDTLS_DEBUG - /* In order to make that work in mbedtls MBEDTLS_DEBUG_C must be defined. */ - mbedtls_ssl_conf_dbg(&backend->config, mbed_debug, data); - /* - 0 No debug - * - 1 Error - * - 2 State change - * - 3 Informational - * - 4 Verbose - */ - mbedtls_debug_set_threshold(4); -#endif - /* give application a chance to interfere with mbedTLS set up. */ if(data->set.ssl.fsslctx) { CURLcode result = (*data->set.ssl.fsslctx)(data, &backend->config, @@ -914,20 +932,24 @@ mbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) return CURLE_OK; } -static CURLcode -mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) +static CURLcode mbed_connect_step2(struct Curl_cfilter *cf, + struct Curl_easy *data) { +#if defined(MBEDTLS_PK_WRITE_C) || defined(HAS_ALPN_MBEDTLS) CURLcode result; +#endif int ret; struct ssl_connect_data *connssl = cf->ctx; struct mbed_ssl_backend_data *backend = (struct mbed_ssl_backend_data *)connssl->backend; +#ifdef MBEDTLS_PK_WRITE_C #ifndef CURL_DISABLE_PROXY const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf) ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : data->set.str[STRING_SSL_PINNEDPUBLICKEY]; #else const char * const pinnedpubkey = data->set.str[STRING_SSL_PINNEDPUBLICKEY]; +#endif #endif DEBUGASSERT(backend); @@ -959,13 +981,14 @@ mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) { char cipher_str[64]; uint16_t cipher_id; - cipher_id = (uint16_t) - mbedtls_ssl_get_ciphersuite_id_from_ssl(&backend->ssl); + cipher_id = + (uint16_t)mbedtls_ssl_get_ciphersuite_id_from_ssl(&backend->ssl); mbed_cipher_suite_get_str(cipher_id, cipher_str, sizeof(cipher_str), TRUE); infof(data, "mbedTLS: %s Handshake complete, cipher is %s", mbedtls_ssl_get_version(&backend->ssl), cipher_str); } +#ifdef MBEDTLS_PK_WRITE_C if(pinnedpubkey) { int size; const mbedtls_x509_crt *peercert; @@ -978,12 +1001,12 @@ mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) return CURLE_SSL_PINNEDPUBKEYNOTMATCH; } - p = calloc(1, sizeof(*p)); + p = curlx_calloc(1, sizeof(*p)); if(!p) return CURLE_OUT_OF_MEMORY; - pubkey = malloc(PUB_DER_MAX_BYTES); + pubkey = curlx_malloc(PUB_DER_MAX_BYTES); if(!pubkey) { result = CURLE_OUT_OF_MEMORY; @@ -1015,11 +1038,12 @@ mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) &pubkey[PUB_DER_MAX_BYTES - size], size); pinnedpubkey_error: mbedtls_x509_crt_free(p); - free(p); - free(pubkey); + curlx_free(p); + curlx_free(pubkey); if(result) return result; } +#endif #ifdef HAS_ALPN_MBEDTLS if(connssl->alpn) { @@ -1039,13 +1063,12 @@ mbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) return CURLE_OK; } -static CURLcode -mbed_new_session(struct Curl_cfilter *cf, struct Curl_easy *data) +static CURLcode mbed_new_session(struct Curl_cfilter *cf, + struct Curl_easy *data) { struct ssl_connect_data *connssl = cf->ctx; struct mbed_ssl_backend_data *backend = (struct mbed_ssl_backend_data *)connssl->backend; - struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); mbedtls_ssl_session session; bool msession_alloced = FALSE; struct Curl_ssl_session *sc_session = NULL; @@ -1056,7 +1079,7 @@ mbed_new_session(struct Curl_cfilter *cf, struct Curl_easy *data) int ret; DEBUGASSERT(backend); - if(!ssl_config->primary.cache_session) + if(!Curl_ssl_scache_use(cf, data)) return CURLE_OK; mbedtls_ssl_session_init(&session); @@ -1074,7 +1097,7 @@ mbed_new_session(struct Curl_cfilter *cf, struct Curl_easy *data) goto out; } - sdata = malloc(slen); + sdata = curlx_malloc(slen); if(!sdata) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -1099,13 +1122,12 @@ mbed_new_session(struct Curl_cfilter *cf, struct Curl_easy *data) out: if(msession_alloced) mbedtls_ssl_session_free(&session); - free(sdata); + curlx_free(sdata); return result; } static CURLcode mbed_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *mem, size_t len, - size_t *pnwritten) + const void *mem, size_t len, size_t *pnwritten) { struct ssl_connect_data *connssl = cf->ctx; struct mbed_ssl_backend_data *backend = @@ -1117,7 +1139,7 @@ static CURLcode mbed_send(struct Curl_cfilter *cf, struct Curl_easy *data, DEBUGASSERT(backend); *pnwritten = 0; connssl->io_need = CURL_SSL_IO_NEED_NONE; - /* mbedtls is picky when a mbedtls_ssl_write) was previously blocked. + /* mbedTLS is picky when a mbedtls_ssl_write() was previously blocked. * It requires to be called with the same amount of bytes again, or it * will lose bytes, e.g. reporting all was sent but they were not. * Remember the blocked length and use that when set. */ @@ -1272,17 +1294,12 @@ static void mbedtls_close(struct Curl_cfilter *cf, struct Curl_easy *data) Curl_safefree(backend->ciphersuites); mbedtls_ssl_config_free(&backend->config); mbedtls_ssl_free(&backend->ssl); - mbedtls_ctr_drbg_free(&backend->ctr_drbg); -#ifndef HAS_THREADING_SUPPORT - mbedtls_entropy_free(&backend->entropy); -#endif /* HAS_THREADING_SUPPORT */ backend->initialized = FALSE; } } static CURLcode mbed_recv(struct Curl_cfilter *cf, struct Curl_easy *data, - char *buf, size_t buffersize, - size_t *pnread) + char *buf, size_t buffersize, size_t *pnread) { struct ssl_connect_data *connssl = cf->ctx; struct mbed_ssl_backend_data *backend = @@ -1299,6 +1316,7 @@ static CURLcode mbed_recv(struct Curl_cfilter *cf, struct Curl_easy *data, if(nread > 0) *pnread = (size_t)nread; else { + char errorbuf[128]; CURL_TRC_CF(data, cf, "mbedtls_ssl_read(len=%zu) -> -0x%04X", buffersize, -nread); switch(nread) { @@ -1318,14 +1336,12 @@ static CURLcode mbed_recv(struct Curl_cfilter *cf, struct Curl_easy *data, case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: result = CURLE_OK; break; - default: { - char errorbuf[128]; + default: mbedtls_strerror(nread, errorbuf, sizeof(errorbuf)); failf(data, "ssl_read returned: (-0x%04X) %s", -nread, errorbuf); result = CURLE_RECV_ERROR; break; } - } } return result; } @@ -1346,33 +1362,12 @@ static size_t mbedtls_version(char *buffer, size_t size) static CURLcode mbedtls_random(struct Curl_easy *data, unsigned char *entropy, size_t length) { -#ifdef MBEDTLS_CTR_DRBG_C - int ret; - mbedtls_entropy_context ctr_entropy; - mbedtls_ctr_drbg_context ctr_drbg; - mbedtls_entropy_init(&ctr_entropy); - mbedtls_ctr_drbg_init(&ctr_drbg); + psa_status_t status; (void)data; - ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, - &ctr_entropy, NULL, 0); + status = psa_generate_random(entropy, length); - if(!ret) - ret = mbedtls_ctr_drbg_random(&ctr_drbg, entropy, length); - - mbedtls_ctr_drbg_free(&ctr_drbg); - mbedtls_entropy_free(&ctr_entropy); - - return ret == 0 ? CURLE_OK : CURLE_FAILED_INIT; -#elif defined(MBEDTLS_HAVEGE_C) - mbedtls_havege_state hs; - mbedtls_havege_init(&hs); - mbedtls_havege_random(&hs, entropy, length); - mbedtls_havege_free(&hs); - return CURLE_OK; -#else - return CURLE_NOT_BUILT_IN; -#endif + return status == PSA_SUCCESS ? CURLE_OK : CURLE_FAILED_INIT; } static CURLcode mbedtls_connect(struct Curl_cfilter *cf, @@ -1432,34 +1427,47 @@ static CURLcode mbedtls_connect(struct Curl_cfilter *cf, */ static int mbedtls_init(void) { - if(!Curl_mbedtlsthreadlock_thread_setup()) - return 0; -#ifdef HAS_THREADING_SUPPORT - entropy_init_mutex(&ts_entropy); -#endif -#ifdef MBEDTLS_USE_PSA_CRYPTO /* requires mbedTLS 3.6.0+ */ - { - int ret; -#ifdef HAS_THREADING_SUPPORT - Curl_mbedtlsthreadlock_lock_function(0); -#endif - ret = psa_crypto_init(); -#ifdef HAS_THREADING_SUPPORT - Curl_mbedtlsthreadlock_unlock_function(0); +#if MBEDTLS_VERSION_NUMBER < 0x04000000 + int ret = 0; #endif - if(ret != PSA_SUCCESS) - return 0; + psa_status_t status; + status = psa_crypto_init(); + + if(status != PSA_SUCCESS) + return 0; + +#if MBEDTLS_VERSION_NUMBER < 0x04000000 + mbedtls_ctr_drbg_init(&rng.drbg); + mbedtls_entropy_init(&rng.entropy); + + ret = mbedtls_ctr_drbg_seed(&rng.drbg, mbedtls_entropy_func, &rng.entropy, + NULL, 0); + + if(ret) { + failf(NULL, " failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n", + (unsigned int)-ret); + return 0; } -#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* To prevent an adversary from reading your random data, + you can enable prediction resistance. + + Entropy is gathered before each mbedtls_ctr_drbg_random() call. + Only use this if you have ample supply of good entropy.*/ + mbedtls_ctr_drbg_set_prediction_resistance(&rng.drbg, + MBEDTLS_CTR_DRBG_PR_ON); +#endif return 1; } static void mbedtls_cleanup(void) { -#ifdef HAS_THREADING_SUPPORT - entropy_cleanup_mutex(&ts_entropy); + mbedtls_psa_crypto_free(); + +#if MBEDTLS_VERSION_NUMBER < 0x04000000 + mbedtls_ctr_drbg_free(&rng.drbg); + mbedtls_entropy_free(&rng.entropy); #endif - (void)Curl_mbedtlsthreadlock_thread_cleanup(); } static bool mbedtls_data_pending(struct Curl_cfilter *cf, @@ -1479,11 +1487,19 @@ static CURLcode mbedtls_sha256sum(const unsigned char *input, unsigned char *sha256sum, size_t sha256len) { - (void)sha256len; - /* returns 0 on success, otherwise failure */ - if(mbedtls_sha256(input, inputlen, sha256sum, 0) != 0) +#if defined(PSA_WANT_ALG_SHA_256) && PSA_WANT_ALG_SHA_256 /* mbedTLS 4+ */ + psa_status_t status; + size_t sha256len_actual; + status = psa_hash_compute(PSA_ALG_SHA_256, input, inputlen, + sha256sum, sha256len, + &sha256len_actual); + if(status != PSA_SUCCESS) return CURLE_BAD_FUNCTION_ARGUMENT; return CURLE_OK; +#else + (void)sha256len; + return Curl_sha256it(sha256sum, input, inputlen); +#endif } static void *mbedtls_get_internals(struct ssl_connect_data *connssl, diff --git a/lib/vtls/mbedtls_threadlock.c b/lib/vtls/mbedtls_threadlock.c deleted file mode 100644 index ed70308b739d..000000000000 --- a/lib/vtls/mbedtls_threadlock.c +++ /dev/null @@ -1,134 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) Daniel Stenberg, , et al. - * Copyright (C) Hoi-Ho Chan, - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at https://curl.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the 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_MBEDTLS) && \ - ((defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H)) || \ - defined(_WIN32)) - -#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) -# include -# define MBEDTLS_MUTEX_T pthread_mutex_t -#elif defined(_WIN32) -# define MBEDTLS_MUTEX_T HANDLE -#endif - -#include "mbedtls_threadlock.h" - -/* The last 2 #include files should be: */ -#include "../curl_memory.h" -#include "../memdebug.h" - -/* number of thread locks */ -#define NUMT 2 - -/* This array will store all of the mutexes available to Mbedtls. */ -static MBEDTLS_MUTEX_T *mutex_buf = NULL; - -int Curl_mbedtlsthreadlock_thread_setup(void) -{ - int i; - - mutex_buf = calloc(1, NUMT * sizeof(MBEDTLS_MUTEX_T)); - if(!mutex_buf) - return 0; /* error, no number of threads defined */ - - for(i = 0; i < NUMT; i++) { -#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) - if(pthread_mutex_init(&mutex_buf[i], NULL)) - return 0; /* pthread_mutex_init failed */ -#elif defined(_WIN32) - mutex_buf[i] = CreateMutex(0, FALSE, 0); - if(mutex_buf[i] == 0) - return 0; /* CreateMutex failed */ -#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */ - } - - return 1; /* OK */ -} - -int Curl_mbedtlsthreadlock_thread_cleanup(void) -{ - int i; - - if(!mutex_buf) - return 0; /* error, no threads locks defined */ - - for(i = 0; i < NUMT; i++) { -#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) - if(pthread_mutex_destroy(&mutex_buf[i])) - return 0; /* pthread_mutex_destroy failed */ -#elif defined(_WIN32) - if(!CloseHandle(mutex_buf[i])) - return 0; /* CloseHandle failed */ -#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */ - } - free(mutex_buf); - mutex_buf = NULL; - - return 1; /* OK */ -} - -int Curl_mbedtlsthreadlock_lock_function(int n) -{ - if(n < NUMT) { -#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) - if(pthread_mutex_lock(&mutex_buf[n])) { - DEBUGF(curl_mfprintf(stderr, "Error: " - "mbedtlsthreadlock_lock_function failed\n")); - return 0; /* pthread_mutex_lock failed */ - } -#elif defined(_WIN32) - if(WaitForSingleObject(mutex_buf[n], INFINITE) == WAIT_FAILED) { - DEBUGF(curl_mfprintf(stderr, "Error: " - "mbedtlsthreadlock_lock_function failed\n")); - return 0; /* pthread_mutex_lock failed */ - } -#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */ - } - return 1; /* OK */ -} - -int Curl_mbedtlsthreadlock_unlock_function(int n) -{ - if(n < NUMT) { -#if defined(USE_THREADS_POSIX) && defined(HAVE_PTHREAD_H) - if(pthread_mutex_unlock(&mutex_buf[n])) { - DEBUGF(curl_mfprintf(stderr, "Error: " - "mbedtlsthreadlock_unlock_function failed\n")); - return 0; /* pthread_mutex_unlock failed */ - } -#elif defined(_WIN32) - if(!ReleaseMutex(mutex_buf[n])) { - DEBUGF(curl_mfprintf(stderr, "Error: " - "mbedtlsthreadlock_unlock_function failed\n")); - return 0; /* pthread_mutex_lock failed */ - } -#endif /* USE_THREADS_POSIX && HAVE_PTHREAD_H */ - } - return 1; /* OK */ -} - -#endif /* USE_MBEDTLS */ diff --git a/lib/vtls/openssl.c b/lib/vtls/openssl.c index 533acdaf8db7..dcc76a9299aa 100644 --- a/lib/vtls/openssl.c +++ b/lib/vtls/openssl.c @@ -31,8 +31,6 @@ #if defined(USE_QUICHE) || defined(USE_OPENSSL) -#include - /* Wincrypt must be included before anything that could include OpenSSL. */ #ifdef USE_WIN32_CRYPTO #include @@ -46,15 +44,13 @@ #endif #include "../urldata.h" -#include "../sendf.h" +#include "../curl_trc.h" #include "../formdata.h" /* for the boundary function */ #include "../url.h" /* for the ssl config check function */ #include "../curlx/inet_pton.h" #include "openssl.h" #include "../connect.h" -#include "../slist.h" -#include "../select.h" -#include "../curlx/wait.h" +#include "../progress.h" #include "vtls.h" #include "vtls_int.h" #include "vtls_scache.h" @@ -65,10 +61,10 @@ #include "../multiif.h" #include "../curlx/strerr.h" #include "../curlx/strparse.h" +#include "../curlx/strcopy.h" #include "../strdup.h" #include "apple.h" -#include #include #include #ifndef OPENSSL_NO_DSA @@ -76,21 +72,15 @@ #endif #include #include -#include #include #include #include #include -#include #include #include #include -#ifdef HAVE_SSL_SET1_ECH_CONFIG_LIST -#define USE_ECH_OPENSSL -#endif - -#if defined(USE_ECH_OPENSSL) && !defined(HAVE_BORINGSSL_LIKE) +#if defined(HAVE_SSL_SET1_ECH_CONFIG_LIST) && !defined(HAVE_BORINGSSL_LIKE) #include #endif @@ -108,8 +98,10 @@ # if LIBRESSL_VERSION_NUMBER < 0x2090100fL /* 2019-04-13 */ # error "LibreSSL 2.9.1 or later required" # endif -#elif OPENSSL_VERSION_NUMBER < 0x1000201fL /* 2015-03-19 */ -# error "OpenSSL 1.0.2a or later required" +#elif !defined(HAVE_BORINGSSL_LIKE) +# ifndef HAVE_OPENSSL3 /* 2021-09-07 */ +# error "OpenSSL 3.0.0 or later required" +# endif #endif #if defined(HAVE_OPENSSL3) && !defined(OPENSSL_NO_UI_CONSOLE) @@ -123,45 +115,13 @@ static void ossl_provider_cleanup(struct Curl_easy *data); /* AWS-LC fixed a bug with large buffers in v1.61.0 which also introduced * X509_V_ERR_EC_KEY_EXPLICIT_PARAMS. */ -#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ - !defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_IS_BORINGSSL) && \ +#if !defined(LIBRESSL_VERSION_NUMBER) && !defined(OPENSSL_IS_BORINGSSL) && \ (!defined(OPENSSL_IS_AWSLC) || defined(X509_V_ERR_EC_KEY_EXPLICIT_PARAMS)) #define HAVE_SSL_CTX_SET_DEFAULT_READ_BUFFER_LEN 1 #endif -#include "../curlx/warnless.h" - -/* The last #include files should be: */ -#include "../curl_memory.h" -#include "../memdebug.h" - #if defined(USE_OPENSSL_ENGINE) || defined(OPENSSL_HAS_PROVIDERS) #include - -#if OPENSSL_VERSION_NUMBER >= 0x10100000L -#define OSSL_UI_METHOD_CAST(x) (x) -#else -#define OSSL_UI_METHOD_CAST(x) CURL_UNCONST(x) -#endif -#endif - -#if OPENSSL_VERSION_NUMBER >= 0x10100000L /* OpenSSL 1.1.0+ and LibreSSL */ -#define HAVE_X509_GET0_EXTENSIONS 1 /* added in 1.1.0 -pre1 */ -#define HAVE_OPAQUE_EVP_PKEY 1 /* since 1.1.0 -pre3 */ -#define HAVE_OPAQUE_RSA_DSA_DH 1 /* since 1.1.0 -pre5 */ -#define HAVE_ERR_REMOVE_THREAD_STATE_DEPRECATED 1 -#else -/* For OpenSSL before 1.1.0 */ -#define ASN1_STRING_get0_data(x) ASN1_STRING_data(x) -#define X509_get0_notBefore(x) X509_get_notBefore(x) -#define X509_get0_notAfter(x) X509_get_notAfter(x) -#define OpenSSL_version_num() SSLeay() -#endif - -#if OPENSSL_VERSION_NUMBER >= 0x10002003L && \ - OPENSSL_VERSION_NUMBER <= 0x10002FFFL && \ - !defined(OPENSSL_NO_COMP) -#define HAVE_SSL_COMP_FREE_COMPRESSION_METHODS 1 #endif #ifdef HAVE_OPENSSL3 @@ -182,8 +142,7 @@ static void ossl_provider_cleanup(struct Curl_easy *data); * BoringSSL: no * LibreSSL: supported since 3.4.1 (released 2021-10-14) */ -#if ((OPENSSL_VERSION_NUMBER >= 0x10101000L && \ - !defined(LIBRESSL_VERSION_NUMBER)) || \ +#if (!defined(LIBRESSL_VERSION_NUMBER) || \ (defined(LIBRESSL_VERSION_NUMBER) && \ LIBRESSL_VERSION_NUMBER >= 0x3040100fL)) && \ !defined(OPENSSL_IS_BORINGSSL) @@ -198,7 +157,7 @@ static void ossl_provider_cleanup(struct Curl_easy *data); * BoringSSL: supported since 0.20240913.0 (commit 826ce15) * LibreSSL: no */ -#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER) +#ifndef LIBRESSL_VERSION_NUMBER #define HAVE_SSL_CTX_SET1_SIGALGS #endif @@ -208,7 +167,7 @@ static void ossl_provider_cleanup(struct Curl_easy *data); #define OSSL_PACKAGE "BoringSSL" #elif defined(OPENSSL_IS_AWSLC) #define OSSL_PACKAGE "AWS-LC" -#elif defined(USE_NGTCP2) && defined(USE_NGHTTP3) && \ +#elif defined(USE_NGTCP2) && defined(USE_NGHTTP3) && \ !defined(OPENSSL_QUIC_API2) #define OSSL_PACKAGE "quictls" #else @@ -224,30 +183,6 @@ typedef unsigned long sslerr_t; #endif #define ossl_valsize_t numcert_t -#if OPENSSL_VERSION_NUMBER >= 0x10100000L -/* up2date versions of OpenSSL maintain reasonably secure defaults without - * breaking compatibility, so it is better not to override the defaults in curl - */ -#define DEFAULT_CIPHER_SELECTION NULL -#else -/* not the case with old versions of OpenSSL */ -#define DEFAULT_CIPHER_SELECTION \ - "ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH" -#endif - -#if OPENSSL_VERSION_NUMBER >= 0x10100000L -#define HAVE_RANDOM_INIT_BY_DEFAULT 1 -#endif - -/* - * Whether the OpenSSL version has the API needed to support sharing an - * X509_STORE between connections. The API is: - * * `X509_STORE_up_ref` -- Introduced: OpenSSL 1.1.0. - */ -#if OPENSSL_VERSION_NUMBER >= 0x10100000L /* OpenSSL >= 1.1.0 */ -#define HAVE_SSL_X509_STORE_SHARE -#endif - static CURLcode ossl_certchain(struct Curl_easy *data, SSL *ssl); static CURLcode push_certinfo(struct Curl_easy *data, @@ -264,6 +199,13 @@ static CURLcode push_certinfo(struct Curl_easy *data, return result; } +static CURLcode pubkey_show(struct Curl_easy *data, + BIO *mem, + int num, + const char *type, + const char *name, + const BIGNUM *bn) WARN_UNUSED_RESULT; + static CURLcode pubkey_show(struct Curl_easy *data, BIO *mem, int num, @@ -280,27 +222,12 @@ static CURLcode pubkey_show(struct Curl_easy *data, return push_certinfo(data, mem, namebuf, num); } -#ifdef HAVE_OPAQUE_RSA_DSA_DH -#define print_pubkey_BN(_type, _name, _num) \ +#define print_pubkey_BN(_type, _name, _num) \ pubkey_show(data, mem, _num, #_type, #_name, _name) -#else -#define print_pubkey_BN(_type, _name, _num) \ -do { \ - if(_type->_name) { \ - pubkey_show(data, mem, _num, #_type, #_name, _type->_name); \ - } \ -} while(0) -#endif - static int asn1_object_dump(const ASN1_OBJECT *a, char *buf, size_t len) { - int i; -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - i = i2t_ASN1_OBJECT(buf, (int)len, a); -#else - i = i2t_ASN1_OBJECT(buf, (int)len, CURL_UNCONST(a)); -#endif + int i = i2t_ASN1_OBJECT(buf, (int)len, a); return (i >= (int)len); /* buffer too small */ } @@ -310,10 +237,10 @@ static CURLcode X509V3_ext(struct Curl_easy *data, { int i; CURLcode result = CURLE_OK; -#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER) - const STACK_OF(X509_EXTENSION) *exts = extsarg; -#else +#ifdef LIBRESSL_VERSION_NUMBER STACK_OF(X509_EXTENSION) *exts = CURL_UNCONST(extsarg); +#else + const STACK_OF(X509_EXTENSION) *exts = extsarg; #endif if((int)sk_X509_EXTENSION_num(exts) <= 0) @@ -334,7 +261,7 @@ static CURLcode X509V3_ext(struct Curl_easy *data, if(asn1_object_dump(obj, namebuf, sizeof(namebuf))) /* make sure the name is null-terminated */ - namebuf [ sizeof(namebuf) - 1] = 0; + namebuf[sizeof(namebuf) - 1] = 0; if(!X509V3_EXT_print(bio_out, ext, 0, 0)) ASN1_STRING_print(bio_out, (ASN1_STRING *)X509_EXTENSION_get_data(ext)); @@ -349,6 +276,103 @@ static CURLcode X509V3_ext(struct Curl_easy *data, return result; } +static CURLcode get_pkey_rsa(struct Curl_easy *data, + EVP_PKEY *pubkey, BIO *mem, int i) +{ + CURLcode result = CURLE_OK; +#ifndef HAVE_EVP_PKEY_GET_PARAMS + RSA *rsa = EVP_PKEY_get0_RSA(pubkey); +#endif /* !HAVE_EVP_PKEY_GET_PARAMS */ + DECLARE_PKEY_PARAM_BIGNUM(n); + DECLARE_PKEY_PARAM_BIGNUM(e); +#ifdef HAVE_EVP_PKEY_GET_PARAMS + EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_N, &n); + EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_E, &e); +#else + RSA_get0_key(rsa, &n, &e, NULL); +#endif /* HAVE_EVP_PKEY_GET_PARAMS */ + BIO_printf(mem, "%d", n ? BN_num_bits(n) : 0); + result = push_certinfo(data, mem, "RSA Public Key", i); + if(!result) { + result = print_pubkey_BN(rsa, n, i); + if(!result) + result = print_pubkey_BN(rsa, e, i); + } + FREE_PKEY_PARAM_BIGNUM(n); + FREE_PKEY_PARAM_BIGNUM(e); + return result; +} + +static CURLcode get_pkey_dsa(struct Curl_easy *data, + EVP_PKEY *pubkey, BIO *mem, int i) +{ + CURLcode result = CURLE_OK; +#ifndef OPENSSL_NO_DSA +#ifndef HAVE_EVP_PKEY_GET_PARAMS + DSA *dsa = EVP_PKEY_get0_DSA(pubkey); +#endif /* !HAVE_EVP_PKEY_GET_PARAMS */ + DECLARE_PKEY_PARAM_BIGNUM(p); + DECLARE_PKEY_PARAM_BIGNUM(q); + DECLARE_PKEY_PARAM_BIGNUM(g); + DECLARE_PKEY_PARAM_BIGNUM(pub_key); +#ifdef HAVE_EVP_PKEY_GET_PARAMS + EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_P, &p); + EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_Q, &q); + EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_G, &g); + EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_PUB_KEY, &pub_key); +#else + DSA_get0_pqg(dsa, &p, &q, &g); + DSA_get0_key(dsa, &pub_key, NULL); +#endif /* HAVE_EVP_PKEY_GET_PARAMS */ + result = print_pubkey_BN(dsa, p, i); + if(!result) + result = print_pubkey_BN(dsa, q, i); + if(!result) + result = print_pubkey_BN(dsa, g, i); + if(!result) + result = print_pubkey_BN(dsa, pub_key, i); + FREE_PKEY_PARAM_BIGNUM(p); + FREE_PKEY_PARAM_BIGNUM(q); + FREE_PKEY_PARAM_BIGNUM(g); + FREE_PKEY_PARAM_BIGNUM(pub_key); +#endif /* !OPENSSL_NO_DSA */ + return result; +} + +static CURLcode get_pkey_dh(struct Curl_easy *data, + EVP_PKEY *pubkey, BIO *mem, int i) +{ + CURLcode result; +#ifndef HAVE_EVP_PKEY_GET_PARAMS + DH *dh = EVP_PKEY_get0_DH(pubkey); +#endif /* !HAVE_EVP_PKEY_GET_PARAMS */ + DECLARE_PKEY_PARAM_BIGNUM(p); + DECLARE_PKEY_PARAM_BIGNUM(q); + DECLARE_PKEY_PARAM_BIGNUM(g); + DECLARE_PKEY_PARAM_BIGNUM(pub_key); +#ifdef HAVE_EVP_PKEY_GET_PARAMS + EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_P, &p); + EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_Q, &q); + EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_G, &g); + EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_PUB_KEY, &pub_key); +#else + DH_get0_pqg(dh, &p, &q, &g); + DH_get0_key(dh, &pub_key, NULL); +#endif /* HAVE_EVP_PKEY_GET_PARAMS */ + result = print_pubkey_BN(dh, p, i); + if(!result) + result = print_pubkey_BN(dh, q, i); + if(!result) + result = print_pubkey_BN(dh, g, i); + if(!result) + result = print_pubkey_BN(dh, pub_key, i); + FREE_PKEY_PARAM_BIGNUM(p); + FREE_PKEY_PARAM_BIGNUM(q); + FREE_PKEY_PARAM_BIGNUM(g); + FREE_PKEY_PARAM_BIGNUM(pub_key); + return result; +} + static CURLcode ossl_certchain(struct Curl_easy *data, SSL *ssl) { CURLcode result; @@ -364,6 +388,11 @@ static CURLcode ossl_certchain(struct Curl_easy *data, SSL *ssl) return CURLE_SSL_CONNECT_ERROR; numcerts = sk_X509_num(sk); + if(numcerts > MAX_ALLOWED_CERT_AMOUNT) { + failf(data, "%d certificates is more than allowed (%u)", (int)numcerts, + MAX_ALLOWED_CERT_AMOUNT); + return CURLE_SSL_CONNECT_ERROR; + } result = Curl_ssl_init_certinfo(data, (int)numcerts); if(result) @@ -375,6 +404,7 @@ static CURLcode ossl_certchain(struct Curl_easy *data, SSL *ssl) for(i = 0; !result && (i < (int)numcerts); i++) { ASN1_INTEGER *num; + const unsigned char *numdata; X509 *x = sk_X509_value(sk, (ossl_valsize_t)i); EVP_PKEY *pubkey = NULL; int j; @@ -396,15 +426,15 @@ static CURLcode ossl_certchain(struct Curl_easy *data, SSL *ssl) break; num = X509_get_serialNumber(x); - if(num->type == V_ASN1_NEG_INTEGER) + if(ASN1_STRING_type(num) == V_ASN1_NEG_INTEGER) BIO_puts(mem, "-"); - for(j = 0; j < num->length; j++) - BIO_printf(mem, "%02x", num->data[j]); + numdata = ASN1_STRING_get0_data(num); + for(j = 0; j < ASN1_STRING_length(num); j++) + BIO_printf(mem, "%02x", numdata[j]); result = push_certinfo(data, mem, "Serial Number", i); if(result) break; -#ifdef HAVE_X509_GET0_EXTENSIONS { const X509_ALGOR *sigalg = NULL; X509_PUBKEY *xpubkey = NULL; @@ -435,28 +465,6 @@ static CURLcode ossl_certchain(struct Curl_easy *data, SSL *ssl) if(result) break; } -#else - { - /* before OpenSSL 1.0.2 */ - X509_CINF *cinf = x->cert_info; - - i2a_ASN1_OBJECT(mem, cinf->signature->algorithm); - result = push_certinfo(data, mem, "Signature Algorithm", i); - - if(!result) { - i2a_ASN1_OBJECT(mem, cinf->key->algor->algorithm); - result = push_certinfo(data, mem, "Public Key Algorithm", i); - } - - if(!result) - result = X509V3_ext(data, i, cinf->extensions); - - if(result) - break; - - psig = x->signature; - } -#endif ASN1_TIME_print(mem, X509_get0_notBefore(x)); result = push_certinfo(data, mem, "Start date", i); @@ -472,133 +480,26 @@ static CURLcode ossl_certchain(struct Curl_easy *data, SSL *ssl) if(!pubkey) infof(data, " Unable to load public key"); else { - int pktype; -#ifdef HAVE_OPAQUE_EVP_PKEY - pktype = EVP_PKEY_id(pubkey); -#else - pktype = pubkey->type; -#endif - switch(pktype) { - case EVP_PKEY_RSA: { -#ifndef HAVE_EVP_PKEY_GET_PARAMS - RSA *rsa; -#ifdef HAVE_OPAQUE_EVP_PKEY - rsa = EVP_PKEY_get0_RSA(pubkey); -#else - rsa = pubkey->pkey.rsa; -#endif /* HAVE_OPAQUE_EVP_PKEY */ -#endif /* !HAVE_EVP_PKEY_GET_PARAMS */ - - { -#ifdef HAVE_OPAQUE_RSA_DSA_DH - DECLARE_PKEY_PARAM_BIGNUM(n); - DECLARE_PKEY_PARAM_BIGNUM(e); -#ifdef HAVE_EVP_PKEY_GET_PARAMS - EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_N, &n); - EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_E, &e); -#else - RSA_get0_key(rsa, &n, &e, NULL); -#endif /* HAVE_EVP_PKEY_GET_PARAMS */ - BIO_printf(mem, "%d", n ? BN_num_bits(n) : 0); -#else - BIO_printf(mem, "%d", rsa->n ? BN_num_bits(rsa->n) : 0); -#endif /* HAVE_OPAQUE_RSA_DSA_DH */ - result = push_certinfo(data, mem, "RSA Public Key", i); - if(result) - break; - print_pubkey_BN(rsa, n, i); - print_pubkey_BN(rsa, e, i); - FREE_PKEY_PARAM_BIGNUM(n); - FREE_PKEY_PARAM_BIGNUM(e); - } - + switch(EVP_PKEY_id(pubkey)) { + case EVP_PKEY_RSA: + result = get_pkey_rsa(data, pubkey, mem, i); break; - } + case EVP_PKEY_DSA: - { -#ifndef OPENSSL_NO_DSA -#ifndef HAVE_EVP_PKEY_GET_PARAMS - DSA *dsa; -#ifdef HAVE_OPAQUE_EVP_PKEY - dsa = EVP_PKEY_get0_DSA(pubkey); -#else - dsa = pubkey->pkey.dsa; -#endif /* HAVE_OPAQUE_EVP_PKEY */ -#endif /* !HAVE_EVP_PKEY_GET_PARAMS */ - { -#ifdef HAVE_OPAQUE_RSA_DSA_DH - DECLARE_PKEY_PARAM_BIGNUM(p); - DECLARE_PKEY_PARAM_BIGNUM(q); - DECLARE_PKEY_PARAM_BIGNUM(g); - DECLARE_PKEY_PARAM_BIGNUM(pub_key); -#ifdef HAVE_EVP_PKEY_GET_PARAMS - EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_P, &p); - EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_Q, &q); - EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_G, &g); - EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_PUB_KEY, &pub_key); -#else - DSA_get0_pqg(dsa, &p, &q, &g); - DSA_get0_key(dsa, &pub_key, NULL); -#endif /* HAVE_EVP_PKEY_GET_PARAMS */ -#endif /* HAVE_OPAQUE_RSA_DSA_DH */ - print_pubkey_BN(dsa, p, i); - print_pubkey_BN(dsa, q, i); - print_pubkey_BN(dsa, g, i); - print_pubkey_BN(dsa, pub_key, i); - FREE_PKEY_PARAM_BIGNUM(p); - FREE_PKEY_PARAM_BIGNUM(q); - FREE_PKEY_PARAM_BIGNUM(g); - FREE_PKEY_PARAM_BIGNUM(pub_key); - } -#endif /* !OPENSSL_NO_DSA */ + result = get_pkey_dsa(data, pubkey, mem, i); break; - } - case EVP_PKEY_DH: { -#ifndef HAVE_EVP_PKEY_GET_PARAMS - DH *dh; -#ifdef HAVE_OPAQUE_EVP_PKEY - dh = EVP_PKEY_get0_DH(pubkey); -#else - dh = pubkey->pkey.dh; -#endif /* HAVE_OPAQUE_EVP_PKEY */ -#endif /* !HAVE_EVP_PKEY_GET_PARAMS */ - { -#ifdef HAVE_OPAQUE_RSA_DSA_DH - DECLARE_PKEY_PARAM_BIGNUM(p); - DECLARE_PKEY_PARAM_BIGNUM(q); - DECLARE_PKEY_PARAM_BIGNUM(g); - DECLARE_PKEY_PARAM_BIGNUM(pub_key); -#ifdef HAVE_EVP_PKEY_GET_PARAMS - EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_P, &p); - EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_Q, &q); - EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_G, &g); - EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_PUB_KEY, &pub_key); -#else - DH_get0_pqg(dh, &p, &q, &g); - DH_get0_key(dh, &pub_key, NULL); -#endif /* HAVE_EVP_PKEY_GET_PARAMS */ - print_pubkey_BN(dh, p, i); - print_pubkey_BN(dh, q, i); - print_pubkey_BN(dh, g, i); -#else - print_pubkey_BN(dh, p, i); - print_pubkey_BN(dh, g, i); -#endif /* HAVE_OPAQUE_RSA_DSA_DH */ - print_pubkey_BN(dh, pub_key, i); - FREE_PKEY_PARAM_BIGNUM(p); - FREE_PKEY_PARAM_BIGNUM(q); - FREE_PKEY_PARAM_BIGNUM(g); - FREE_PKEY_PARAM_BIGNUM(pub_key); - } + + case EVP_PKEY_DH: + result = get_pkey_dh(data, pubkey, mem, i); break; } - } EVP_PKEY_free(pubkey); } if(!result && psig) { - for(j = 0; j < psig->length; j++) - BIO_printf(mem, "%02x:", psig->data[j]); + const unsigned char *psigdata = ASN1_STRING_get0_data(psig); + for(j = 0; j < ASN1_STRING_length(psig); j++) + BIO_printf(mem, "%02x:", psigdata[j]); result = push_certinfo(data, mem, "Signature", i); } @@ -621,21 +522,10 @@ static CURLcode ossl_certchain(struct Curl_easy *data, SSL *ssl) #ifdef USE_OPENSSL -#if OPENSSL_VERSION_NUMBER < 0x10100000L -#define BIO_set_init(x,v) ((x)->init=(v)) -#define BIO_get_data(x) ((x)->ptr) -#define BIO_set_data(x,v) ((x)->ptr=(v)) -#define BIO_get_shutdown(x) ((x)->shutdown) -#define BIO_set_shutdown(x,v) ((x)->shutdown=(v)) -#endif /* HAVE_PRE_1_1_API */ - static int ossl_bio_cf_create(BIO *bio) { BIO_set_shutdown(bio, 1); BIO_set_init(bio, 1); -#if OPENSSL_VERSION_NUMBER < 0x10100000L - bio->num = -1; -#endif BIO_set_data(bio, NULL); return 1; } @@ -694,7 +584,8 @@ static int ossl_bio_cf_out_write(BIO *bio, const char *buf, int blen) if(blen < 0) return 0; - result = Curl_conn_cf_send(cf->next, data, buf, (size_t)blen, FALSE, + result = Curl_conn_cf_send(cf->next, data, + (const uint8_t *)buf, (size_t)blen, FALSE, &nwritten); CURL_TRC_CF(data, cf, "ossl_bio_cf_out_write(len=%d) -> %d, %zu", blen, result, nwritten); @@ -754,30 +645,6 @@ static int ossl_bio_cf_in_read(BIO *bio, char *buf, int blen) return result ? -1 : (int)nread; } -#if OPENSSL_VERSION_NUMBER < 0x10100000L - -static BIO_METHOD ossl_bio_cf_meth_1_0 = { - BIO_TYPE_MEM, - "OpenSSL CF BIO", - ossl_bio_cf_out_write, - ossl_bio_cf_in_read, - NULL, /* puts is never called */ - NULL, /* gets is never called */ - ossl_bio_cf_ctrl, - ossl_bio_cf_create, - ossl_bio_cf_destroy, - NULL -}; - -static BIO_METHOD *ossl_bio_cf_method_create(void) -{ - return &ossl_bio_cf_meth_1_0; -} - -#define ossl_bio_cf_method_free(m) Curl_nop_stmt - -#else - static BIO_METHOD *ossl_bio_cf_method_create(void) { BIO_METHOD *m = BIO_meth_new(BIO_TYPE_MEM, "OpenSSL CF BIO"); @@ -797,9 +664,6 @@ static void ossl_bio_cf_method_free(BIO_METHOD *m) BIO_meth_free(m); } -#endif - - #ifdef HAVE_KEYLOG_CALLBACK static void ossl_keylog_callback(const SSL *ssl, const char *line) { @@ -812,8 +676,7 @@ static void ossl_keylog_callback(const SSL *ssl, const char *line) * ossl_log_tls12_secret is called by libcurl to make the CLIENT_RANDOMs if the * OpenSSL being used does not have native support for doing that. */ -static void -ossl_log_tls12_secret(const SSL *ssl, bool *keylog_done) +static void ossl_log_tls12_secret(const SSL *ssl, bool *keylog_done) { const SSL_SESSION *session; unsigned char client_random[SSL3_RANDOM_SIZE]; @@ -829,19 +692,9 @@ ossl_log_tls12_secret(const SSL *ssl, bool *keylog_done) return; } -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - /* ssl->s3 is not checked in OpenSSL 1.1.0-pre6, but let's assume that - * we have a valid SSL context if we have a non-NULL session. */ SSL_get_client_random(ssl, client_random, SSL3_RANDOM_SIZE); master_key_length = (int) SSL_SESSION_get_master_key(session, master_key, SSL_MAX_MASTER_KEY_LENGTH); -#else - if(ssl->s3 && session->master_key_length > 0) { - master_key_length = session->master_key_length; - memcpy(master_key, session->master_key, session->master_key_length); - memcpy(client_random, ssl->s3->client_random, SSL3_RANDOM_SIZE); - } -#endif ERR_pop_to_mark(); @@ -921,15 +774,13 @@ static char *ossl_strerror(unsigned long error, char *buf, size_t size) if(!*buf) { const char *msg = error ? "Unknown error" : "No error"; - if(strlen(msg) < size) - strcpy(buf, msg); + curlx_strcopy(buf, size, msg, strlen(msg)); } return buf; } -static int passwd_callback(char *buf, int num, int encrypting, - void *password) +static int passwd_callback(char *buf, int num, int encrypting, void *password) { DEBUGASSERT(encrypting == 0); @@ -963,58 +814,8 @@ static CURLcode ossl_seed(struct Curl_easy *data) data->multi->ssl_seeded = TRUE; return CURLE_OK; } -#ifdef HAVE_RANDOM_INIT_BY_DEFAULT - /* with OpenSSL 1.1.0+, a failed RAND_status is a showstopper */ failf(data, "Insufficient randomness"); return CURLE_SSL_CONNECT_ERROR; -#else - - /* fallback to a custom seeding of the PRNG using a hash based on a current - time */ - do { - unsigned char randb[64]; - size_t len = sizeof(randb); - size_t i, i_max; - for(i = 0, i_max = len / sizeof(struct curltime); i < i_max; ++i) { - struct curltime tv = curlx_now(); - curlx_wait_ms(1); - tv.tv_sec *= (time_t)i + 1; - tv.tv_usec *= (int)i + 2; - tv.tv_sec ^= ((curlx_now().tv_sec + (time_t)curlx_now().tv_usec) * - (time_t)(i + 3)) << 8; - tv.tv_usec ^= (int) ((curlx_now().tv_sec + (time_t)curlx_now().tv_usec) * - (time_t)(i + 4)) << 16; - memcpy(&randb[i * sizeof(struct curltime)], &tv, - sizeof(struct curltime)); - } - RAND_add(randb, (int)len, (double)len/2); - } while(!rand_enough()); - - /* - * Number of bytes to read from the random number seed file. This must be - * a finite value (because some entropy "files" like /dev/urandom have - * an infinite length), but must be large enough to provide enough - * entropy to properly seed OpenSSL's PRNG. - */ -# define RAND_LOAD_LENGTH 1024 - - { - /* generates a default path for the random seed file */ - char fname[256]; - fname[0] = 0; /* blank it first */ - RAND_file_name(fname, sizeof(fname)); - if(fname[0]) { - /* we got a filename to try */ - RAND_load_file(fname, RAND_LOAD_LENGTH); - if(rand_enough()) - return CURLE_OK; - } - } - - infof(data, "libcurl is now using a weak random seed"); - return rand_enough() ? CURLE_OK : - CURLE_SSL_CONNECT_ERROR; /* confusing error code */ -#endif } #ifndef SSL_FILETYPE_ENGINE @@ -1119,8 +920,7 @@ static int use_certificate_blob(SSL_CTX *ctx, const struct curl_blob *blob, } else if(type == SSL_FILETYPE_PEM) { /* ERR_R_PEM_LIB; */ - x = PEM_read_bio_X509(in, NULL, - passwd_callback, CURL_UNCONST(key_passwd)); + x = PEM_read_bio_X509(in, NULL, passwd_callback, CURL_UNCONST(key_passwd)); } else { ret = 0; @@ -1166,9 +966,9 @@ static int use_privatekey_blob(SSL_CTX *ctx, const struct curl_blob *blob, return ret; } -static int -use_certificate_chain_blob(SSL_CTX *ctx, const struct curl_blob *blob, - const char *key_passwd) +static int use_certificate_chain_blob(SSL_CTX *ctx, + const struct curl_blob *blob, + const char *key_passwd) { int ret = 0; X509 *x = NULL; @@ -1198,8 +998,7 @@ use_certificate_chain_blob(SSL_CTX *ctx, const struct curl_blob *blob, } while((ca = PEM_read_bio_X509(in, NULL, passwd_callback, - CURL_UNCONST(key_passwd))) - != NULL) { + CURL_UNCONST(key_passwd))) != NULL) { if(!SSL_CTX_add0_chain_cert(ctx, ca)) { X509_free(ca); @@ -1241,10 +1040,9 @@ static int enginecheck(struct Curl_easy *data, } if(data->state.engine) { - UI_METHOD *ui_method = - UI_create_method(OSSL_UI_METHOD_CAST("curl user interface")); + UI_METHOD *ui_method = UI_create_method("curl user interface"); if(!ui_method) { - failf(data, "unable do create " OSSL_PACKAGE " user-interface method"); + failf(data, "unable to create " OSSL_PACKAGE " user-interface method"); return 0; } UI_method_set_opener(ui_method, UI_method_get_opener(UI_OpenSSL())); @@ -1303,10 +1101,9 @@ static int providercheck(struct Curl_easy *data, EVP_PKEY *priv_key = NULL; OSSL_STORE_CTX *store = NULL; OSSL_STORE_INFO *info = NULL; - UI_METHOD *ui_method = - UI_create_method(OSSL_UI_METHOD_CAST("curl user interface")); + UI_METHOD *ui_method = UI_create_method("curl user interface"); if(!ui_method) { - failf(data, "unable do create " OSSL_PACKAGE " user-interface method"); + failf(data, "unable to create " OSSL_PACKAGE " user-interface method"); return 0; } UI_method_set_opener(ui_method, UI_method_get_opener(UI_OpenSSL())); @@ -1321,6 +1118,7 @@ static int providercheck(struct Curl_easy *data, failf(data, "Failed to open OpenSSL store: %s", ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer))); + UI_destroy_method(ui_method); return 0; } if(OSSL_STORE_expect(store, OSSL_STORE_INFO_PKEY) != 1) { @@ -1407,16 +1205,15 @@ static int engineload(struct Curl_easy *data, /* Load the certificate from the engine */ if(!ENGINE_ctrl_cmd(data->state.engine, cmd_name, 0, ¶ms, NULL, 1)) { - failf(data, "ssl engine cannot load client cert with id" - " '%s' [%s]", cert_file, + failf(data, "ssl engine cannot load client cert with id '%s' [%s]", + cert_file, ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer))); return 0; } if(!params.cert) { - failf(data, "ssl engine did not initialized the certificate " - "properly."); + failf(data, "ssl engine did not initialized the certificate properly."); return 0; } @@ -1424,6 +1221,7 @@ static int engineload(struct Curl_easy *data, failf(data, "unable to set client certificate [%s]", ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer))); + X509_free(params.cert); return 0; } X509_free(params.cert); /* we do not need the handle any more... */ @@ -1466,6 +1264,8 @@ static int providerload(struct Curl_easy *data, OSSL_STORE_CTX *store = OSSL_STORE_open_ex(cert_file, data->state.libctx, NULL, NULL, NULL, NULL, NULL, NULL); + int rc; + if(!store) { failf(data, "Failed to open OpenSSL store: %s", ossl_strerror(ERR_get_error(), error_buffer, @@ -1494,13 +1294,15 @@ static int providerload(struct Curl_easy *data, return 0; } - if(SSL_CTX_use_certificate(ctx, cert) != 1) { + rc = SSL_CTX_use_certificate(ctx, cert); + X509_free(cert); /* we do not need the handle any more... */ + + if(rc != 1) { failf(data, "unable to set client certificate [%s]", ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer))); return 0; } - X509_free(cert); /* we do not need the handle any more... */ } else { failf(data, "crypto provider not set, cannot load certificate"); @@ -1533,8 +1335,7 @@ static int pkcs12load(struct Curl_easy *data, if(cert_blob) { cert_bio = BIO_new_mem_buf(cert_blob->data, (int)(cert_blob->len)); if(!cert_bio) { - failf(data, - "BIO_new_mem_buf NULL, " OSSL_PACKAGE " error %s", + failf(data, "BIO_new_mem_buf NULL, " OSSL_PACKAGE " error %s", ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer)) ); return 0; @@ -1543,8 +1344,7 @@ static int pkcs12load(struct Curl_easy *data, else { cert_bio = BIO_new(BIO_s_file()); if(!cert_bio) { - failf(data, - "BIO_new return NULL, " OSSL_PACKAGE " error %s", + failf(data, "BIO_new return NULL, " OSSL_PACKAGE " error %s", ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer)) ); return 0; @@ -1566,14 +1366,10 @@ static int pkcs12load(struct Curl_easy *data, return 0; } - PKCS12_PBE_add(); - if(!PKCS12_parse(p12, key_passwd, &pri, &x509, &ca)) { - failf(data, - "could not parse PKCS12 file, check password, " OSSL_PACKAGE + failf(data, "could not parse PKCS12 file, check password, " OSSL_PACKAGE " error %s", - ossl_strerror(ERR_get_error(), error_buffer, - sizeof(error_buffer)) ); + ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer))); PKCS12_free(p12); return 0; } @@ -1581,17 +1377,14 @@ static int pkcs12load(struct Curl_easy *data, PKCS12_free(p12); if(SSL_CTX_use_certificate(ctx, x509) != 1) { - failf(data, - "could not load PKCS12 client certificate, " OSSL_PACKAGE + failf(data, "could not load PKCS12 client certificate, " OSSL_PACKAGE " error %s", - ossl_strerror(ERR_get_error(), error_buffer, - sizeof(error_buffer)) ); + ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer))); goto fail; } if(SSL_CTX_use_PrivateKey(ctx, pri) != 1) { - failf(data, "unable to use private key from PKCS12 file '%s'", - cert_file); + failf(data, "unable to use private key from PKCS12 file '%s'", cert_file); goto fail; } @@ -1641,7 +1434,6 @@ static int pkcs12load(struct Curl_easy *data, return 1; } - static CURLcode client_cert(struct Curl_easy *data, SSL_CTX* ctx, char *cert_file, @@ -1680,10 +1472,10 @@ static CURLcode client_cert(struct Curl_easy *data, failf(data, "could not load PEM client certificate from %s, " OSSL_PACKAGE " error %s, " - "(no key found, wrong pass phrase, or wrong file format?)", + "(no key found, wrong passphrase, or wrong file format?)", (cert_blob ? "CURLOPT_SSLCERT_BLOB" : cert_file), ossl_strerror(ERR_get_error(), error_buffer, - sizeof(error_buffer)) ); + sizeof(error_buffer))); return CURLE_SSL_CERTPROBLEM; } break; @@ -1700,21 +1492,21 @@ static CURLcode client_cert(struct Curl_easy *data, failf(data, "could not load ASN1 client certificate from %s, " OSSL_PACKAGE " error %s, " - "(no key found, wrong pass phrase, or wrong file format?)", + "(no key found, wrong passphrase, or wrong file format?)", (cert_blob ? "CURLOPT_SSLCERT_BLOB" : cert_file), ossl_strerror(ERR_get_error(), error_buffer, - sizeof(error_buffer)) ); + sizeof(error_buffer))); return CURLE_SSL_CERTPROBLEM; } break; case SSL_FILETYPE_ENGINE: - if(!engineload(data, ctx, cert_file)) + if(!cert_file || !engineload(data, ctx, cert_file)) return CURLE_SSL_CERTPROBLEM; break; case SSL_FILETYPE_PROVIDER: - if(!providerload(data, ctx, cert_file)) + if(!cert_file || !providerload(data, ctx, cert_file)) return CURLE_SSL_CERTPROBLEM; break; @@ -1789,13 +1581,7 @@ static CURLcode client_cert(struct Curl_easy *data, /* If RSA is used, do not check the private key if its flags indicate * it does not support it. */ EVP_PKEY *priv_key = SSL_get_privatekey(ssl); - int pktype; -#ifdef HAVE_OPAQUE_EVP_PKEY - pktype = EVP_PKEY_id(priv_key); -#else - pktype = priv_key->type; -#endif - if(pktype == EVP_PKEY_RSA) { + if(EVP_PKEY_id(priv_key) == EVP_PKEY_RSA) { RSA *rsa = EVP_PKEY_get1_RSA(priv_key); if(RSA_flags(rsa) & RSA_METHOD_FLAG_NO_CHECK) check_privkey = FALSE; @@ -1838,8 +1624,8 @@ static CURLcode x509_name_oneline(X509_NAME *a, struct dynbuf *d) if(rc != -1) { BIO_get_mem_ptr(bio_out, &biomem); result = curlx_dyn_addn(d, biomem->data, biomem->length); - BIO_free(bio_out); } + BIO_free(bio_out); } return result; } @@ -1853,7 +1639,6 @@ static CURLcode x509_name_oneline(X509_NAME *a, struct dynbuf *d) */ static int ossl_init(void) { -#if OPENSSL_VERSION_NUMBER >= 0x10100000L const uint64_t flags = #ifdef OPENSSL_INIT_ENGINE_ALL_BUILTIN /* not present in BoringSSL */ @@ -1866,28 +1651,6 @@ static int ossl_init(void) #endif 0; OPENSSL_init_ssl(flags, NULL); -#else - OPENSSL_load_builtin_modules(); - -#ifdef USE_OPENSSL_ENGINE - ENGINE_load_builtin_engines(); -#endif - -#ifndef CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG - CONF_modules_load_file(NULL, NULL, - CONF_MFLAGS_DEFAULT_SECTION| - CONF_MFLAGS_IGNORE_MISSING_FILE); -#endif - - /* Let's get nice error messages */ - SSL_load_error_strings(); - - /* Init the global ciphers and digests */ - if(!SSLeay_add_ssl_algorithms()) - return 0; - - OpenSSL_add_all_algorithms(); -#endif Curl_tls_keylog_open(); @@ -1897,32 +1660,6 @@ static int ossl_init(void) /* Global cleanup */ static void ossl_cleanup(void) { -#if OPENSSL_VERSION_NUMBER >= 0x10100000L - /* OpenSSL 1.1 deprecates all these cleanup functions and - turns them into no-ops in OpenSSL 1.0 compatibility mode */ -#else - /* Free ciphers and digests lists */ - EVP_cleanup(); - -#ifdef USE_OPENSSL_ENGINE - /* Free engine list */ - ENGINE_cleanup(); -#endif - - /* Free OpenSSL error strings */ - ERR_free_strings(); - - /* Free thread local error state, destroying hash upon zero refcount */ - ERR_remove_thread_state(NULL); - - /* Free all memory allocated by all configuration modules */ - CONF_modules_free(); - -#ifdef HAVE_SSL_COMP_FREE_COMPRESSION_METHODS - SSL_COMP_free_compression_methods(); -#endif -#endif - Curl_tls_keylog_close(); } @@ -2065,7 +1802,7 @@ static CURLcode ossl_set_provider(struct Curl_easy *data, const char *iname) if(!libctx) return CURLE_OUT_OF_MEMORY; if(propq) { - data->state.propq = strdup(propq); + data->state.propq = curlx_strdup(propq); if(!data->state.propq) { OSSL_LIB_CTX_free(libctx); return CURLE_OUT_OF_MEMORY; @@ -2088,20 +1825,17 @@ static CURLcode ossl_set_provider(struct Curl_easy *data, const char *iname) return CURLE_OK; } - data->state.provider = - OSSL_PROVIDER_try_load(data->state.libctx, name, 1); + data->state.provider = OSSL_PROVIDER_try_load(data->state.libctx, name, 1); if(!data->state.provider) { char error_buffer[256]; failf(data, "Failed to initialize provider: %s", - ossl_strerror(ERR_get_error(), error_buffer, - sizeof(error_buffer))); + ossl_strerror(ERR_get_error(), error_buffer, sizeof(error_buffer))); ossl_provider_cleanup(data); return CURLE_SSL_ENGINE_NOTFOUND; } /* load the base provider as well */ - data->state.baseprov = - OSSL_PROVIDER_try_load(data->state.libctx, "base", 1); + data->state.baseprov = OSSL_PROVIDER_try_load(data->state.libctx, "base", 1); if(!data->state.baseprov) { ossl_provider_cleanup(data); failf(data, "Failed to load base"); @@ -2113,7 +1847,6 @@ static CURLcode ossl_set_provider(struct Curl_easy *data, const char *iname) } #endif - static CURLcode ossl_shutdown(struct Curl_cfilter *cf, struct Curl_easy *data, bool send_shutdown, bool *done) @@ -2276,13 +2009,6 @@ static void ossl_close_all(struct Curl_easy *data) #ifdef OPENSSL_HAS_PROVIDERS ossl_provider_cleanup(data); #endif -#ifndef HAVE_ERR_REMOVE_THREAD_STATE_DEPRECATED - /* OpenSSL 1.0.1 and 1.0.2 build an error queue that is stored per-thread - so we need to clean it here in case the thread will be killed. All OpenSSL - code should extract the error in association with the error so clearing - this queue here should be harmless at worst. */ - ERR_remove_thread_state(NULL); -#endif } /* ====================================================== */ @@ -2383,11 +2109,11 @@ static CURLcode ossl_verifyhost(struct Curl_easy *data, if(check->type == target) { /* get data and length */ const char *altptr = (const char *)ASN1_STRING_get0_data(check->d.ia5); - size_t altlen = (size_t) ASN1_STRING_length(check->d.ia5); + size_t altlen = (size_t)ASN1_STRING_length(check->d.ia5); switch(target) { case GEN_DNS: /* name/pattern comparison */ - /* The OpenSSL manpage explicitly says: "In general it cannot be + /* The OpenSSL man page explicitly says: "In general it cannot be assumed that the data returned by ASN1_STRING_data() is null terminated or does not contain embedded nulls." But also that "The actual format of the data will depend on the actual string @@ -2411,8 +2137,7 @@ static CURLcode ossl_verifyhost(struct Curl_easy *data, our server IP address is */ if((altlen == addrlen) && !memcmp(altptr, &addr, altlen)) { matched = TRUE; - infof(data, - " subjectAltName: \"%s\" matches cert's IP address!", + infof(data, " subjectAltName: \"%s\" matches cert's IP address!", peer->dispname); } break; @@ -2487,8 +2212,7 @@ static CURLcode ossl_verifyhost(struct Curl_easy *data, /* error already detected, pass through */ ; else if(!cn) { - failf(data, - "SSL: unable to obtain common name from peer certificate"); + failf(data, "SSL: unable to obtain common name from peer certificate"); result = CURLE_PEER_FAILED_VERIFICATION; } else if(!Curl_cert_hostcheck((const char *)cn, cnlen, @@ -2769,7 +2493,7 @@ static void ossl_trace(int direction, int ssl_ver, int content_type, const void *buf, size_t len, SSL *ssl, void *userp) { - const char *verstr = "???"; + const char *verstr; struct Curl_cfilter *cf = userp; struct Curl_easy *data = NULL; char unknown[32]; @@ -2804,13 +2528,9 @@ static void ossl_trace(int direction, int ssl_ver, int content_type, verstr = "TLSv1.2"; break; #endif -#ifdef TLS1_3_VERSION /* OpenSSL 1.1.1+, all forks */ case TLS1_3_VERSION: verstr = "TLSv1.3"; break; -#endif - case 0: - break; default: curl_msnprintf(unknown, sizeof(unknown), "(%x)", ssl_ver); verstr = unknown; @@ -2876,7 +2596,6 @@ static void ossl_trace(int direction, int ssl_ver, int content_type, # define HAS_ALPN_OPENSSL #endif -#if OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0 */ static CURLcode ossl_set_ssl_version_min_max(struct Curl_cfilter *cf, SSL_CTX *ctx, unsigned int ssl_version_min) @@ -2894,6 +2613,8 @@ ossl_set_ssl_version_min_max(struct Curl_cfilter *cf, SSL_CTX *ctx, long ossl_ssl_version_min = 0; long ossl_ssl_version_max = 0; #endif + /* it cannot be default here */ + DEBUGASSERT(curl_ssl_version_min != CURL_SSLVERSION_DEFAULT); switch(curl_ssl_version_min) { case CURL_SSLVERSION_TLSv1: /* TLS 1.x */ case CURL_SSLVERSION_TLSv1_0: @@ -2906,24 +2627,8 @@ ossl_set_ssl_version_min_max(struct Curl_cfilter *cf, SSL_CTX *ctx, ossl_ssl_version_min = TLS1_2_VERSION; break; case CURL_SSLVERSION_TLSv1_3: -#ifdef TLS1_3_VERSION ossl_ssl_version_min = TLS1_3_VERSION; break; -#else - return CURLE_NOT_BUILT_IN; -#endif - } - - /* CURL_SSLVERSION_DEFAULT means that no option was selected. - We do not want to pass 0 to SSL_CTX_set_min_proto_version as - it would enable all versions down to the lowest supported by - the library. - So we skip this, and stay with the library default - */ - if(curl_ssl_version_min != CURL_SSLVERSION_DEFAULT) { - if(!SSL_CTX_set_min_proto_version(ctx, ossl_ssl_version_min)) { - return CURLE_SSL_CONNECT_ERROR; - } } /* ... then, TLS max version */ @@ -2940,11 +2645,9 @@ ossl_set_ssl_version_min_max(struct Curl_cfilter *cf, SSL_CTX *ctx, case CURL_SSLVERSION_MAX_TLSv1_2: ossl_ssl_version_max = TLS1_2_VERSION; break; -#ifdef TLS1_3_VERSION case CURL_SSLVERSION_MAX_TLSv1_3: ossl_ssl_version_max = TLS1_3_VERSION; break; -#endif case CURL_SSLVERSION_MAX_NONE: /* none selected */ case CURL_SSLVERSION_MAX_DEFAULT: /* max selected */ default: @@ -2955,86 +2658,21 @@ ossl_set_ssl_version_min_max(struct Curl_cfilter *cf, SSL_CTX *ctx, break; } - if(!SSL_CTX_set_max_proto_version(ctx, ossl_ssl_version_max)) { + if(!SSL_CTX_set_min_proto_version(ctx, ossl_ssl_version_min) || + !SSL_CTX_set_max_proto_version(ctx, ossl_ssl_version_max)) return CURLE_SSL_CONNECT_ERROR; - } return CURLE_OK; } -#endif #ifdef HAVE_BORINGSSL_LIKE typedef uint32_t ctx_option_t; #elif defined(HAVE_OPENSSL3) typedef uint64_t ctx_option_t; -#elif OPENSSL_VERSION_NUMBER >= 0x10100000L && \ - !defined(LIBRESSL_VERSION_NUMBER) -typedef unsigned long ctx_option_t; -#else +#elif defined(LIBRESSL_VERSION_NUMBER) typedef long ctx_option_t; -#endif - -#if OPENSSL_VERSION_NUMBER < 0x10100000L /* 1.1.0 */ -static CURLcode -ossl_set_ssl_version_min_max_legacy(ctx_option_t *ctx_options, - struct Curl_cfilter *cf, - struct Curl_easy *data) -{ - struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); - long ssl_version = conn_config->version; - long ssl_version_max = conn_config->version_max; - - (void)data; /* In case it is unused. */ - - switch(ssl_version) { - case CURL_SSLVERSION_TLSv1_3: -#ifdef TLS1_3_VERSION - { - struct ssl_connect_data *connssl = cf->ctx; - struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend; - DEBUGASSERT(octx); - SSL_CTX_set_max_proto_version(octx->ssl_ctx, TLS1_3_VERSION); - *ctx_options |= SSL_OP_NO_TLSv1_2; - } #else - (void)ctx_options; - failf(data, OSSL_PACKAGE " was built without TLS 1.3 support"); - return CURLE_NOT_BUILT_IN; -#endif - FALLTHROUGH(); - case CURL_SSLVERSION_TLSv1_2: - *ctx_options |= SSL_OP_NO_TLSv1_1; - FALLTHROUGH(); - case CURL_SSLVERSION_TLSv1_1: - *ctx_options |= SSL_OP_NO_TLSv1; - FALLTHROUGH(); - case CURL_SSLVERSION_TLSv1_0: - case CURL_SSLVERSION_TLSv1: - break; - } - - switch(ssl_version_max) { - case CURL_SSLVERSION_MAX_TLSv1_0: - *ctx_options |= SSL_OP_NO_TLSv1_1; - FALLTHROUGH(); - case CURL_SSLVERSION_MAX_TLSv1_1: - *ctx_options |= SSL_OP_NO_TLSv1_2; - FALLTHROUGH(); - case CURL_SSLVERSION_MAX_TLSv1_2: -#ifdef TLS1_3_VERSION - *ctx_options |= SSL_OP_NO_TLSv1_3; -#endif - break; - case CURL_SSLVERSION_MAX_TLSv1_3: -#ifdef TLS1_3_VERSION - break; -#else - failf(data, OSSL_PACKAGE " was built without TLS 1.3 support"); - return CURLE_NOT_BUILT_IN; -#endif - } - return CURLE_OK; -} +typedef unsigned long ctx_option_t; #endif CURLcode Curl_ossl_add_session(struct Curl_cfilter *cf, @@ -3046,7 +2684,6 @@ CURLcode Curl_ossl_add_session(struct Curl_cfilter *cf, unsigned char *quic_tp, size_t quic_tp_len) { - const struct ssl_config_data *config; unsigned char *der_session_buf = NULL; unsigned char *qtp_clone = NULL; CURLcode result = CURLE_OK; @@ -3054,8 +2691,7 @@ CURLcode Curl_ossl_add_session(struct Curl_cfilter *cf, if(!cf || !data) goto out; - config = Curl_ssl_cf_get_config(cf, data); - if(config->primary.cache_session) { + if(Curl_ssl_scache_use(cf, data)) { struct Curl_ssl_session *sc_session = NULL; size_t der_session_size; unsigned char *der_session_ptr; @@ -3067,7 +2703,7 @@ CURLcode Curl_ossl_add_session(struct Curl_cfilter *cf, goto out; } - der_session_buf = der_session_ptr = malloc(der_session_size); + der_session_buf = der_session_ptr = curlx_malloc(der_session_size); if(!der_session_buf) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -3104,7 +2740,7 @@ CURLcode Curl_ossl_add_session(struct Curl_cfilter *cf, } out: - free(der_session_buf); + curlx_free(der_session_buf); return result; } @@ -3113,7 +2749,7 @@ CURLcode Curl_ossl_add_session(struct Curl_cfilter *cf, */ static int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) { - struct Curl_cfilter *cf = (struct Curl_cfilter*) SSL_get_app_data(ssl); + struct Curl_cfilter *cf = (struct Curl_cfilter *)SSL_get_app_data(ssl); if(cf) { struct Curl_easy *data = CF_DATA_CURRENT(cf); struct ssl_connect_data *connssl = cf->ctx; @@ -3261,7 +2897,7 @@ static CURLcode ossl_win_load_store(struct Curl_easy *data, */ if(CertGetEnhancedKeyUsage(pContext, 0, NULL, &req_size)) { if(req_size && req_size > enhkey_usage_size) { - void *tmp = realloc(enhkey_usage, req_size); + void *tmp = curlx_realloc(enhkey_usage, req_size); if(!tmp) { failf(data, "SSL: Out of memory allocating for OID list"); @@ -3319,7 +2955,7 @@ static CURLcode ossl_win_load_store(struct Curl_easy *data, X509_free(x509); } - free(enhkey_usage); + curlx_free(enhkey_usage); CertFreeCertificateContext(pContext); CertCloseStore(hStore, 0); @@ -3488,6 +3124,7 @@ static CURLcode ossl_populate_x509_store(struct Curl_cfilter *cf, CURLcode result = CURLE_OK; X509_LOOKUP *lookup = NULL; const char * const ssl_crlfile = ssl_config->primary.CRLfile; + unsigned long x509flags = 0; CURL_TRC_CF(data, cf, "configuring OpenSSL's x509 trust store"); if(!store) @@ -3513,8 +3150,7 @@ static CURLcode ossl_populate_x509_store(struct Curl_cfilter *cf, failf(data, "error loading CRL file: %s", ssl_crlfile); return CURLE_SSL_CRL_BADFILE; } - X509_STORE_set_flags(store, - X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); + x509flags = X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL; infof(data, " CRLfile: %s", ssl_crlfile); } @@ -3524,77 +3160,79 @@ static CURLcode ossl_populate_x509_store(struct Curl_cfilter *cf, determine that in a reliable manner. https://web.archive.org/web/20190422050538/rt.openssl.org/Ticket/Display.html?id=3621 */ - X509_STORE_set_flags(store, X509_V_FLAG_TRUSTED_FIRST); + x509flags |= X509_V_FLAG_TRUSTED_FIRST; + if(!ssl_config->no_partialchain && !ssl_crlfile) { /* Have intermediate certificates in the trust store be treated as - trust-anchors, in the same way as self-signed root CA certificates - are. This allows users to verify servers using the intermediate cert - only, instead of needing the whole chain. + trust-anchors, in the same way as self-signed root CA certificates are. + This allows users to verify servers using the intermediate cert only, + instead of needing the whole chain. Due to OpenSSL bug https://github.com/openssl/openssl/issues/5081 we cannot do partial chains with a CRL check. */ - X509_STORE_set_flags(store, X509_V_FLAG_PARTIAL_CHAIN); + x509flags |= X509_V_FLAG_PARTIAL_CHAIN; } + (void)X509_STORE_set_flags(store, x509flags); return result; } -#ifdef HAVE_SSL_X509_STORE_SHARE - /* key to use at `multi->proto_hash` */ -#define MPROTO_OSSL_X509_KEY "tls:ossl:x509:share" +#define MPROTO_OSSL_X509_KEY "tls:ossl:x509:share" struct ossl_x509_share { char *CAfile; /* CAfile path used to generate X509 store */ X509_STORE *store; /* cached X509 store or NULL if none */ struct curltime time; /* when the cached store was created */ BIT(store_is_empty); /* no certs/paths/blobs are in the store */ + BIT(no_partialchain); /* keep partial chain state */ }; static void oss_x509_share_free(void *key, size_t key_len, void *p) { struct ossl_x509_share *share = p; - DEBUGASSERT(key_len == (sizeof(MPROTO_OSSL_X509_KEY)-1)); + DEBUGASSERT(key_len == (sizeof(MPROTO_OSSL_X509_KEY) - 1)); DEBUGASSERT(!memcmp(MPROTO_OSSL_X509_KEY, key, key_len)); (void)key; (void)key_len; if(share->store) { X509_STORE_free(share->store); } - free(share->CAfile); - free(share); + curlx_free(share->CAfile); + curlx_free(share); } -static bool -ossl_cached_x509_store_expired(const struct Curl_easy *data, - const struct ossl_x509_share *mb) +static bool ossl_cached_x509_store_expired(struct Curl_easy *data, + const struct ossl_x509_share *mb) { const struct ssl_general_config *cfg = &data->set.general_ssl; if(cfg->ca_cache_timeout < 0) return FALSE; else { - struct curltime now = curlx_now(); - timediff_t elapsed_ms = curlx_timediff(now, mb->time); + timediff_t elapsed_ms = curlx_ptimediff_ms(Curl_pgrs_now(data), &mb->time); timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000; return elapsed_ms >= timeout_ms; } } -static bool -ossl_cached_x509_store_different(struct Curl_cfilter *cf, - const struct ossl_x509_share *mb) +static bool ossl_cached_x509_store_different(struct Curl_cfilter *cf, + const struct Curl_easy *data, + const struct ossl_x509_share *mb) { 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, CURL_UNCONST(data)); + if(mb->no_partialchain != ssl_config->no_partialchain) + return TRUE; if(!mb->CAfile || !conn_config->CAfile) return mb->CAfile != conn_config->CAfile; - return strcmp(mb->CAfile, conn_config->CAfile); } static X509_STORE *ossl_get_cached_x509_store(struct Curl_cfilter *cf, - const struct Curl_easy *data, + struct Curl_easy *data, bool *pempty) { struct Curl_multi *multi = data->multi; @@ -3605,10 +3243,10 @@ static X509_STORE *ossl_get_cached_x509_store(struct Curl_cfilter *cf, *pempty = TRUE; share = multi ? Curl_hash_pick(&multi->proto_hash, CURL_UNCONST(MPROTO_OSSL_X509_KEY), - sizeof(MPROTO_OSSL_X509_KEY)-1) : NULL; + sizeof(MPROTO_OSSL_X509_KEY) - 1) : NULL; if(share && share->store && !ossl_cached_x509_store_expired(data, share) && - !ossl_cached_x509_store_different(cf, share)) { + !ossl_cached_x509_store_different(cf, data, share)) { store = share->store; *pempty = share->store_is_empty; } @@ -3617,7 +3255,7 @@ static X509_STORE *ossl_get_cached_x509_store(struct Curl_cfilter *cf, } static void ossl_set_cached_x509_store(struct Curl_cfilter *cf, - const struct Curl_easy *data, + struct Curl_easy *data, X509_STORE *store, bool is_empty) { @@ -3630,26 +3268,28 @@ static void ossl_set_cached_x509_store(struct Curl_cfilter *cf, return; share = Curl_hash_pick(&multi->proto_hash, CURL_UNCONST(MPROTO_OSSL_X509_KEY), - sizeof(MPROTO_OSSL_X509_KEY)-1); + sizeof(MPROTO_OSSL_X509_KEY) - 1); if(!share) { - share = calloc(1, sizeof(*share)); + share = curlx_calloc(1, sizeof(*share)); if(!share) return; if(!Curl_hash_add2(&multi->proto_hash, CURL_UNCONST(MPROTO_OSSL_X509_KEY), - sizeof(MPROTO_OSSL_X509_KEY)-1, + sizeof(MPROTO_OSSL_X509_KEY) - 1, share, oss_x509_share_free)) { - free(share); + curlx_free(share); return; } } if(X509_STORE_up_ref(store)) { char *CAfile = NULL; + struct ssl_config_data *ssl_config = + Curl_ssl_cf_get_config(cf, CURL_UNCONST(data)); if(conn_config->CAfile) { - CAfile = strdup(conn_config->CAfile); + CAfile = curlx_strdup(conn_config->CAfile); if(!CAfile) { X509_STORE_free(store); return; @@ -3658,13 +3298,14 @@ static void ossl_set_cached_x509_store(struct Curl_cfilter *cf, if(share->store) { X509_STORE_free(share->store); - free(share->CAfile); + curlx_free(share->CAfile); } - share->time = curlx_now(); + share->time = *Curl_pgrs_now(data); share->store = store; share->store_is_empty = is_empty; share->CAfile = CAfile; + share->no_partialchain = ssl_config->no_partialchain; } } @@ -3708,25 +3349,6 @@ CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf, return result; } -#else /* HAVE_SSL_X509_STORE_SHARE */ -CURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf, - struct Curl_easy *data, - struct ossl_ctx *octx) -{ - CURLcode result; - X509_STORE *store; - - ERR_set_mark(); - - store = SSL_CTX_get_cert_store(octx->ssl_ctx); - result = ossl_populate_x509_store(cf, data, octx, store); - - ERR_pop_to_mark(); - - return result; -} -#endif /* HAVE_SSL_X509_STORE_SHARE */ - static CURLcode ossl_init_session_and_alpns(struct ossl_ctx *octx, @@ -3745,7 +3367,7 @@ ossl_init_session_and_alpns(struct ossl_ctx *octx, Curl_alpn_copy(&alpns, alpns_requested); octx->reused_session = FALSE; - if(ssl_config->primary.cache_session && !conn_cfg->verifystatus) { + if(Curl_ssl_scache_use(cf, data) && !conn_cfg->verifystatus) { struct Curl_ssl_session *scs = NULL; result = Curl_ssl_scache_take(cf, data, peer->scache_key, &scs); @@ -3777,8 +3399,10 @@ ossl_init_session_and_alpns(struct ossl_ctx *octx, bool do_early_data = FALSE; if(sess_reuse_cb) { result = sess_reuse_cb(cf, data, &alpns, scs, &do_early_data); - if(result) + if(result) { + SSL_SESSION_free(ssl_session); return result; + } } if(do_early_data) { /* We only try the ALPN protocol the session used before, @@ -3787,6 +3411,7 @@ ossl_init_session_and_alpns(struct ossl_ctx *octx, } } #else + (void)ssl_config; (void)sess_reuse_cb; #endif } @@ -3818,7 +3443,7 @@ ossl_init_session_and_alpns(struct ossl_ctx *octx, return CURLE_OK; } -#ifdef USE_ECH_OPENSSL +#ifdef HAVE_SSL_SET1_ECH_CONFIG_LIST static CURLcode ossl_init_ech(struct ossl_ctx *octx, struct Curl_cfilter *cf, struct Curl_easy *data, @@ -3857,25 +3482,23 @@ static CURLcode ossl_init_ech(struct ossl_ctx *octx, if(data->set.tls_ech & CURLECH_HARD) return result; } - if(SSL_set1_ech_config_list(octx->ssl, ech_config, - ech_config_len) != 1) { + if(SSL_set1_ech_config_list(octx->ssl, ech_config, ech_config_len) != 1) { infof(data, "ECH: SSL_ECH_set1_ech_config_list failed"); if(data->set.tls_ech & CURLECH_HARD) { - free(ech_config); + curlx_free(ech_config); return CURLE_SSL_CONNECT_ERROR; } } - free(ech_config); + curlx_free(ech_config); trying_ech_now = 1; # else - ech_config = (unsigned char *) data->set.str[STRING_ECH_CONFIG]; + ech_config = (unsigned char *)data->set.str[STRING_ECH_CONFIG]; if(!ech_config) { infof(data, "ECH: ECHConfig from command line empty"); return CURLE_SSL_CONNECT_ERROR; } ech_config_len = strlen(data->set.str[STRING_ECH_CONFIG]); - if(SSL_set1_ech_config_list(octx->ssl, ech_config, - ech_config_len) != 1) { + if(SSL_set1_ech_config_list(octx->ssl, ech_config, ech_config_len) != 1) { infof(data, "ECH: SSL_ECH_set1_ech_config_list failed"); if(data->set.tls_ech & CURLECH_HARD) return CURLE_SSL_CONNECT_ERROR; @@ -3933,24 +3556,23 @@ static CURLcode ossl_init_ech(struct ossl_ctx *octx, infof(data, "ECH: inner: '%s', outer: '%s'", peer->hostname ? peer->hostname : "NULL", outername); result = SSL_ech_set1_server_names(octx->ssl, - peer->hostname, outername, - 0 /* do send outer */); + peer->hostname, outername, + 0 /* do send outer */); if(result != 1) { infof(data, "ECH: rv failed to set server name(s) %d [ERROR]", result); return CURLE_SSL_CONNECT_ERROR; } } # endif /* HAVE_BORINGSSL_LIKE */ - if(trying_ech_now - && SSL_set_min_proto_version(octx->ssl, TLS1_3_VERSION) != 1) { + if(trying_ech_now && + SSL_set_min_proto_version(octx->ssl, TLS1_3_VERSION) != 1) { infof(data, "ECH: cannot force TLSv1.3 [ERROR]"); return CURLE_SSL_CONNECT_ERROR; } return CURLE_OK; } -#endif /* USE_ECH_OPENSSL */ - +#endif /* HAVE_SSL_SET1_ECH_CONFIG_LIST */ static CURLcode ossl_init_ssl(struct ossl_ctx *octx, struct Curl_cfilter *cf, @@ -3985,19 +3607,18 @@ static CURLcode ossl_init_ssl(struct ossl_ctx *octx, } } -#ifdef USE_ECH_OPENSSL +#ifdef HAVE_SSL_SET1_ECH_CONFIG_LIST { CURLcode result = ossl_init_ech(octx, cf, data, peer); if(result) return result; } -#endif /* USE_ECH_OPENSSL */ +#endif /* HAVE_SSL_SET1_ECH_CONFIG_LIST */ return ossl_init_session_and_alpns(octx, cf, data, peer, alpns_requested, sess_reuse_cb); } - static CURLcode ossl_init_method(struct Curl_cfilter *cf, struct Curl_easy *data, struct ssl_peer *peer, @@ -4019,11 +3640,7 @@ static CURLcode ossl_init_method(struct Curl_cfilter *cf, case CURL_SSLVERSION_TLSv1_2: case CURL_SSLVERSION_TLSv1_3: /* it will be handled later with the context options */ -#if OPENSSL_VERSION_NUMBER >= 0x10100000L *pmethod = TLS_client_method(); -#else - *pmethod = SSLv23_client_method(); -#endif break; case CURL_SSLVERSION_SSLv2: failf(data, "No SSLv2 support"); @@ -4039,6 +3656,7 @@ static CURLcode ossl_init_method(struct Curl_cfilter *cf, case TRNSPRT_QUIC: *pssl_version_min = CURL_SSLVERSION_TLSv1_3; if(conn_config->version_max && + (conn_config->version_max != CURL_SSLVERSION_MAX_DEFAULT) && (conn_config->version_max != CURL_SSLVERSION_MAX_TLSv1_3)) { failf(data, "QUIC needs at least TLS version 1.3"); return CURLE_SSL_CONNECT_ERROR; @@ -4046,10 +3664,8 @@ static CURLcode ossl_init_method(struct Curl_cfilter *cf, #ifdef USE_OPENSSL_QUIC *pmethod = OSSL_QUIC_client_method(); -#elif (OPENSSL_VERSION_NUMBER >= 0x10100000L) - *pmethod = TLS_method(); #else - *pmethod = SSLv23_client_method(); + *pmethod = TLS_method(); #endif break; default: @@ -4060,7 +3676,6 @@ static CURLcode ossl_init_method(struct Curl_cfilter *cf, return *pmethod ? CURLE_OK : CURLE_SSL_CONNECT_ERROR; } - CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, struct Curl_cfilter *cf, struct Curl_easy *data, @@ -4124,7 +3739,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, /* OpenSSL contains code to work around lots of bugs and flaws in various SSL-implementations. SSL_CTX_set_options() is used to enabled those - work-arounds. The manpage for this option states that SSL_OP_ALL enables + work-arounds. The man page for this option states that SSL_OP_ALL enables all the work-arounds and that "It is usually safe to use SSL_OP_ALL to enable the bug workaround options if compatibility with somewhat broken implementations is desired." @@ -4175,7 +3790,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, /* "--tlsv" options mean TLS >= version */ case CURL_SSLVERSION_DEFAULT: - case CURL_SSLVERSION_TLSv1: /* TLS >= version 1.0 */ + case CURL_SSLVERSION_TLSv1: /* TLS >= version 1.0 */ case CURL_SSLVERSION_TLSv1_0: /* TLS >= version 1.0 */ case CURL_SSLVERSION_TLSv1_1: /* TLS >= version 1.1 */ case CURL_SSLVERSION_TLSv1_2: /* TLS >= version 1.2 */ @@ -4185,11 +3800,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, ctx_options |= SSL_OP_NO_SSLv2; ctx_options |= SSL_OP_NO_SSLv3; -#if OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0 */ result = ossl_set_ssl_version_min_max(cf, octx->ssl_ctx, ssl_version_min); -#else - result = ossl_set_ssl_version_min_max_legacy(&ctx_options, cf, data); -#endif if(result) return result; break; @@ -4206,7 +3817,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, OpenSSL supports processing "jumbo TLS record" (8 TLS records) in one go for some algorithms, so match that here. Experimentation shows that a slightly larger buffer is needed - to avoid short reads. + to avoid short reads. However using a large buffer (8 packets) actually decreases performance. 4 packets is better. @@ -4220,7 +3831,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, ciphers = conn_config->cipher_list; if(!ciphers && (peer->transport != TRNSPRT_QUIC)) - ciphers = DEFAULT_CIPHER_SELECTION; + ciphers = NULL; if(ciphers && (ssl_version_min < CURL_SSLVERSION_TLSv1_3)) { if(!SSL_CTX_set_cipher_list(octx->ssl_ctx, ciphers)) { failf(data, "failed setting cipher list: %s", ciphers); @@ -4234,6 +3845,7 @@ CURLcode Curl_ossl_ctx_init(struct ossl_ctx *octx, const char *ciphers13 = conn_config->cipher_list13; if(ciphers13 && (!conn_config->version_max || + (conn_config->version_max == CURL_SSLVERSION_MAX_DEFAULT) || (conn_config->version_max >= CURL_SSLVERSION_MAX_TLSv1_3))) { if(!SSL_CTX_set_ciphersuites(octx->ssl_ctx, ciphers13)) { failf(data, "failed setting TLS 1.3 cipher suite: %s", ciphers13); @@ -4393,8 +4005,7 @@ static CURLcode ossl_on_session_reuse(struct Curl_cfilter *cf, return result; } -void Curl_ossl_report_handshake(struct Curl_easy *data, - struct ossl_ctx *octx) +void Curl_ossl_report_handshake(struct Curl_easy *data, struct ossl_ctx *octx) { #ifndef CURL_DISABLE_VERBOSE_STRINGS if(Curl_trc_is_verbose(data)) { @@ -4422,7 +4033,6 @@ void Curl_ossl_report_handshake(struct Curl_easy *data, (void)data; (void)octx; #endif /* CURL_DISABLE_VERBOSE_STRINGS */ - } static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, @@ -4476,9 +4086,9 @@ static CURLcode ossl_connect_step1(struct Curl_cfilter *cf, return CURLE_OK; } -#ifdef USE_ECH_OPENSSL +#ifdef HAVE_SSL_SET1_ECH_CONFIG_LIST /* If we have retry configs, then trace those out */ -static void ossl_trace_ech_retry_configs(struct Curl_easy *data, SSL* ssl, +static void ossl_trace_ech_retry_configs(struct Curl_easy *data, SSL *ssl, int reason) { CURLcode result = CURLE_OK; @@ -4486,7 +4096,7 @@ static void ossl_trace_ech_retry_configs(struct Curl_easy *data, SSL* ssl, int rv = 1; # ifndef HAVE_BORINGSSL_LIKE char *inner = NULL; - unsigned char *rcs = NULL; + uint8_t *rcs = NULL; char *outer = NULL; # else const char *inner = NULL; @@ -4510,10 +4120,10 @@ static void ossl_trace_ech_retry_configs(struct Curl_easy *data, SSL* ssl, char *b64str = NULL; size_t blen = 0; - result = curlx_base64_encode((const char *)rcs, rcl, &b64str, &blen); + result = curlx_base64_encode(rcs, rcl, &b64str, &blen); if(!result && b64str) { infof(data, "ECH: retry_configs %s", b64str); - free(b64str); + curlx_free(b64str); #ifndef HAVE_BORINGSSL_LIKE rv = SSL_ech_get1_status(ssl, &inner, &outer); infof(data, "ECH: retry_configs for %s from %s, %d %d", @@ -4604,7 +4214,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf, else { /* untreated error */ sslerr_t errdetail; - char error_buffer[256]=""; + char error_buffer[256] = ""; CURLcode result; long lerr; int lib; @@ -4647,7 +4257,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf, ossl_strerror(errdetail, error_buffer, sizeof(error_buffer))); } #endif -#ifdef USE_ECH_OPENSSL +#ifdef HAVE_SSL_SET1_ECH_CONFIG_LIST else if((lib == ERR_LIB_SSL) && # ifndef HAVE_BORINGSSL_LIKE (reason == SSL_R_ECH_REQUIRED)) { @@ -4676,7 +4286,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf, * the SO_ERROR is also lost. */ if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) { - char extramsg[80]=""; + char extramsg[80] = ""; int sockerr = SOCKERRNO; if(sockerr && detail == SSL_ERROR_SYSCALL) @@ -4694,7 +4304,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf, connssl->connecting_state = ssl_connect_3; Curl_ossl_report_handshake(data, octx); -#if defined(USE_ECH_OPENSSL) && !defined(HAVE_BORINGSSL_LIKE) +#if defined(HAVE_SSL_SET1_ECH_CONFIG_LIST) && !defined(HAVE_BORINGSSL_LIKE) if(ECH_ENABLED(data)) { char *inner = NULL, *outer = NULL; const char *status = NULL; @@ -4731,7 +4341,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf, break; default: status = "unexpected status"; - infof(data, "ECH: unexpected status %d",rv); + infof(data, "ECH: unexpected status %d", rv); } infof(data, "ECH: result: status is %s, inner is %s, outer is %s", (status ? status : "NULL"), @@ -4752,7 +4362,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf, else { infof(data, "ECH: result: status is not attempted"); } -#endif /* USE_ECH_OPENSSL && !HAVE_BORINGSSL_LIKE */ +#endif /* HAVE_SSL_SET1_ECH_CONFIG_LIST && !HAVE_BORINGSSL_LIKE */ #ifdef HAS_ALPN_OPENSSL /* Sets data and len to negotiated protocol, len is 0 if no protocol was @@ -4775,7 +4385,7 @@ static CURLcode ossl_connect_step2(struct Curl_cfilter *cf, * Heavily modified from: * https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#OpenSSL */ -static CURLcode ossl_pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert, +static CURLcode ossl_pkp_pin_peer_pubkey(struct Curl_easy *data, X509 *cert, const char *pinnedpubkey) { /* Scratch */ @@ -4799,7 +4409,7 @@ static CURLcode ossl_pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert, if(len1 < 1) break; /* failed */ - buff1 = temp = malloc(len1); + buff1 = temp = curlx_malloc(len1); if(!buff1) break; /* failed */ @@ -4821,14 +4431,13 @@ static CURLcode ossl_pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert, } while(0); if(buff1) - free(buff1); + curlx_free(buff1); return result; } -#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ - !(defined(LIBRESSL_VERSION_NUMBER) && \ - LIBRESSL_VERSION_NUMBER < 0x3060000fL) && \ +#if !(defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x3060000fL) && \ !defined(HAVE_BORINGSSL_LIKE) && !defined(CURL_DISABLE_VERBOSE_STRINGS) static void infof_certstack(struct Curl_easy *data, const SSL *ssl) { @@ -4845,6 +4454,8 @@ static void infof_certstack(struct Curl_easy *data, const SSL *ssl) certstack = SSL_get_peer_cert_chain(ssl); else certstack = SSL_get0_verified_chain(ssl); + if(!certstack) + return; num_cert_levels = sk_X509_num(certstack); for(cert_level = 0; cert_level < num_cert_levels; cert_level++) { @@ -4860,12 +4471,17 @@ static void infof_certstack(struct Curl_easy *data, const SSL *ssl) const char *type_name; current_cert = sk_X509_value(certstack, cert_level); + if(!current_cert) + continue; + + current_pkey = X509_get0_pubkey(current_cert); + if(!current_pkey) + continue; 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); #ifndef HAVE_OPENSSL3 #define EVP_PKEY_get_security_bits EVP_PKEY_security_bits @@ -4879,14 +4495,13 @@ static void infof_certstack(struct Curl_easy *data, const SSL *ssl) curl_msnprintf(group_name_final, sizeof(group_name_final), "/%s", group_name); } - type_name = current_pkey ? EVP_PKEY_get0_type_name(current_pkey) : NULL; + type_name = EVP_PKEY_get0_type_name(current_pkey); #else get_group_name = 0; type_name = NULL; #endif - infof(data, - " Certificate level %d: " + 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, @@ -4904,8 +4519,8 @@ static CURLcode ossl_check_issuer(struct Curl_cfilter *cf, struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); X509 *issuer = NULL; BIO *fp = NULL; - char err_buf[256]=""; - bool strict = (conn_config->verifypeer || conn_config->verifyhost); + char err_buf[256] = ""; + bool verify_enabled = (conn_config->verifypeer || conn_config->verifyhost); CURLcode result = CURLE_OK; /* e.g. match issuer name with provided issuer certificate */ @@ -4929,7 +4544,7 @@ static CURLcode ossl_check_issuer(struct Curl_cfilter *cf, } if(BIO_read_filename(fp, conn_config->issuercert) <= 0) { - if(strict) + if(verify_enabled) failf(data, "SSL: Unable to open issuer cert (%s)", conn_config->issuercert); result = CURLE_SSL_ISSUER_ERROR; @@ -4940,7 +4555,7 @@ static CURLcode ossl_check_issuer(struct Curl_cfilter *cf, if(fp) { issuer = PEM_read_bio_X509(fp, NULL, ZERO_NULL, NULL); if(!issuer) { - if(strict) + if(verify_enabled) failf(data, "SSL: Unable to read issuer cert (%s)", conn_config->issuercert); result = CURLE_SSL_ISSUER_ERROR; @@ -4948,7 +4563,7 @@ static CURLcode ossl_check_issuer(struct Curl_cfilter *cf, } if(X509_check_issued(issuer, server_cert) != X509_V_OK) { - if(strict) + if(verify_enabled) failf(data, "SSL: Certificate issuer check failed (%s)", conn_config->issuercert); result = CURLE_SSL_ISSUER_ERROR; @@ -4996,8 +4611,6 @@ static CURLcode ossl_infof_cert(struct Curl_cfilter *cf, struct Curl_easy *data, X509 *server_cert) { - struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); - bool strict = (conn_config->verifypeer || conn_config->verifyhost); BIO *mem = NULL; struct dynbuf dname; char err_buf[256] = ""; @@ -5024,22 +4637,18 @@ static CURLcode ossl_infof_cert(struct Curl_cfilter *cf, infof(data, " subject: %s", result ? "[NONE]" : curlx_dyn_ptr(&dname)); ASN1_TIME_print(mem, X509_get0_notBefore(server_cert)); - len = BIO_get_mem_data(mem, (char **) &buf); + len = BIO_get_mem_data(mem, (char **)&buf); infof(data, " start date: %.*s", (int)len, buf); (void)BIO_reset(mem); ASN1_TIME_print(mem, X509_get0_notAfter(server_cert)); - len = BIO_get_mem_data(mem, (char **) &buf); + len = BIO_get_mem_data(mem, (char **)&buf); infof(data, " expire date: %.*s", (int)len, buf); (void)BIO_reset(mem); result = x509_name_oneline(X509_get_issuer_name(server_cert), &dname); - if(result) { - if(strict) - failf(data, "SSL: could not get X509-issuer name"); - result = CURLE_PEER_FAILED_VERIFICATION; + if(result) /* should be only fatal stuff like OOM */ goto out; - } infof(data, " issuer: %s", curlx_dyn_ptr(&dname)); out: @@ -5049,7 +4658,6 @@ static CURLcode ossl_infof_cert(struct Curl_cfilter *cf, } #endif /* ! CURL_DISABLE_VERBOSE_STRINGS */ - #ifdef USE_APPLE_SECTRUST struct ossl_certs_ctx { STACK_OF(X509) *sk; @@ -5092,12 +4700,6 @@ static CURLcode ossl_apple_verify(struct Curl_cfilter *cf, { struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); struct ossl_certs_ctx chain; - long ocsp_len = 0; -#ifdef HAVE_BORINGSSL_LIKE - const uint8_t *ocsp_data = NULL; -#else - unsigned char *ocsp_data = NULL; -#endif CURLcode result; memset(&chain, 0, sizeof(chain)); @@ -5109,13 +4711,24 @@ static CURLcode ossl_apple_verify(struct Curl_cfilter *cf, failf(data, "SSL: could not get peer certificate"); result = CURLE_PEER_FAILED_VERIFICATION; } + else { +#ifdef HAVE_BORINGSSL_LIKE + const uint8_t *ocsp_data = NULL; +#else + unsigned char *ocsp_data = NULL; +#endif + long ocsp_len = 0; + if(conn_config->verifystatus && !octx->reused_session) + ocsp_len = (long)SSL_get_tlsext_status_ocsp_resp(octx->ssl, &ocsp_data); - if(conn_config->verifystatus && !octx->reused_session) - ocsp_len = (long)SSL_get_tlsext_status_ocsp_resp(octx->ssl, &ocsp_data); - - result = Curl_vtls_apple_verify(cf, data, peer, chain.num_certs, - ossl_chain_get_der, &chain, - ocsp_data, ocsp_len); + /* SSL_get_tlsext_status_ocsp_resp() returns the length of the OCSP + response data or -1 if there is no OCSP response data. */ + if(ocsp_len < 0) + ocsp_len = 0; /* no data available */ + result = Curl_vtls_apple_verify(cf, data, peer, chain.num_certs, + ossl_chain_get_der, &chain, + ocsp_data, ocsp_len); + } *pverified = !result; return result; } @@ -5131,12 +4744,14 @@ CURLcode Curl_ossl_check_peer_cert(struct Curl_cfilter *cf, struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); CURLcode result = CURLE_OK; long ossl_verify; - bool strict = (conn_config->verifypeer || conn_config->verifyhost); X509 *server_cert; bool verified = FALSE; +#ifdef USE_APPLE_SECTRUST + bool sectrust_verified = FALSE; +#endif if(data->set.ssl.certinfo && !octx->reused_session) { - /* asked to gather certificate info. Reused sessions don't have cert + /* asked to gather certificate info. Reused sessions do not have cert chains */ result = ossl_certchain(data, octx->ssl); if(result) @@ -5145,7 +4760,8 @@ CURLcode Curl_ossl_check_peer_cert(struct Curl_cfilter *cf, server_cert = SSL_get1_peer_certificate(octx->ssl); if(!server_cert) { - if(!strict) + /* no verification at all, this maybe acceptable */ + if(!(conn_config->verifypeer || conn_config->verifyhost)) goto out; failf(data, "SSL: could not get peer certificate"); @@ -5165,6 +4781,7 @@ CURLcode Curl_ossl_check_peer_cert(struct Curl_cfilter *cf, if(result) goto out; } + /* `verifyhost` is either OK or not requested from here on */ ossl_verify = SSL_get_verify_result(octx->ssl); ssl_config->certverifyresult = ossl_verify; @@ -5174,9 +4791,7 @@ CURLcode Curl_ossl_check_peer_cert(struct Curl_cfilter *cf, infof(data, "SSL certificate verified via OpenSSL."); #ifdef USE_APPLE_SECTRUST - if(!verified && - conn_config->verifypeer && ssl_config->native_ca_store && - (ossl_verify == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY)) { + if(!verified && conn_config->verifypeer && ssl_config->native_ca_store) { /* we verify using Apple SecTrust *unless* OpenSSL already verified. * This may happen if the application intercepted the OpenSSL callback * and installed its own. */ @@ -5186,22 +4801,30 @@ CURLcode Curl_ossl_check_peer_cert(struct Curl_cfilter *cf, if(verified) { infof(data, "SSL certificate verified via Apple SecTrust."); ssl_config->certverifyresult = X509_V_OK; + sectrust_verified = TRUE; } } #endif if(!verified) { /* no trust established, report the OpenSSL status */ - failf(data, "SSL certificate OpenSSL verify result: %s (%ld)", - X509_verify_cert_error_string(ossl_verify), ossl_verify); - result = CURLE_PEER_FAILED_VERIFICATION; - if(conn_config->verifypeer) + if(conn_config->verifypeer) { + failf(data, "SSL certificate OpenSSL verify result: %s (%ld)", + X509_verify_cert_error_string(ossl_verify), ossl_verify); + result = CURLE_PEER_FAILED_VERIFICATION; goto out; + } infof(data, " SSL certificate verification failed, continuing anyway!"); } #if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_OCSP) - if(conn_config->verifystatus && !octx->reused_session) { + if(conn_config->verifystatus && +#ifdef USE_APPLE_SECTRUST + !sectrust_verified && /* already verified via apple sectrust, cannot + * verifystate via OpenSSL in that case as it + * does not have the trust anchors */ +#endif + !octx->reused_session) { /* do not do this after Session ID reuse */ result = verifystatus(cf, data, octx); if(result) @@ -5460,8 +5083,7 @@ static CURLcode ossl_send(struct Curl_cfilter *cf, result = CURLE_AGAIN; octx->blocked_ssl_write_len = memlen; goto out; - case SSL_ERROR_SYSCALL: - { + case SSL_ERROR_SYSCALL: { int sockerr = SOCKERRNO; if(octx->io_result == CURLE_AGAIN) { @@ -5514,7 +5136,6 @@ static CURLcode ossl_recv(struct Curl_cfilter *cf, char error_buffer[256]; unsigned long sslerror; int buffsize; - struct connectdata *conn = cf->conn; struct ssl_connect_data *connssl = cf->ctx; struct ossl_ctx *octx = (struct ossl_ctx *)connssl->backend; CURLcode result = CURLE_OK; @@ -5544,7 +5165,7 @@ static CURLcode ossl_recv(struct Curl_cfilter *cf, if(cf->sockindex == FIRSTSOCKET) /* mark the connection for close if it is indeed the control connection */ - connclose(conn, "TLS close_notify"); + CURL_TRC_CF(data, cf, "TLS close_notify"); break; case SSL_ERROR_WANT_READ: connssl->io_need = CURL_SSL_IO_NEED_RECV; @@ -5625,8 +5246,6 @@ static CURLcode ossl_recv(struct Curl_cfilter *cf, static CURLcode ossl_get_channel_binding(struct Curl_easy *data, int sockindex, struct dynbuf *binding) { - /* required for X509_get_signature_nid support */ -#if OPENSSL_VERSION_NUMBER > 0x10100000L X509 *cert; int algo_nid; const EVP_MD *algo_type; @@ -5649,10 +5268,8 @@ static CURLcode ossl_get_channel_binding(struct Curl_easy *data, int sockindex, break; } - if(cf->next) - cf = cf->next; - - } while(cf->next); + cf = cf->next; + } while(cf); if(!octx) { failf(data, "Failed to find the SSL filter"); @@ -5661,7 +5278,7 @@ static CURLcode ossl_get_channel_binding(struct Curl_easy *data, int sockindex, cert = SSL_get1_peer_certificate(octx->ssl); if(!cert) - /* No server certificate, don't do channel binding */ + /* No server certificate, do not do channel binding */ return CURLE_OK; if(!OBJ_find_sigid_algs(X509_get_signature_nid(cert), &algo_nid, NULL)) { @@ -5703,13 +5320,6 @@ static CURLcode ossl_get_channel_binding(struct Curl_easy *data, int sockindex, error: X509_free(cert); return result; -#else - /* No X509_get_signature_nid support */ - (void)data; - (void)sockindex; - (void)binding; - return CURLE_OK; -#endif } size_t Curl_ossl_version(char *buffer, size_t size) @@ -5738,41 +5348,9 @@ size_t Curl_ossl_version(char *buffer, size_t size) #elif defined(OPENSSL_IS_AWSLC) return curl_msnprintf(buffer, size, "%s/%s", OSSL_PACKAGE, AWSLC_VERSION_NUMBER_STRING); -#elif defined(OPENSSL_VERSION_STRING) /* OpenSSL 3+ */ +#else /* OpenSSL 3+ */ return curl_msnprintf(buffer, size, "%s/%s", OSSL_PACKAGE, OpenSSL_version(OPENSSL_VERSION_STRING)); -#else - /* not LibreSSL, BoringSSL and not using OpenSSL_version */ - - char sub[3]; - unsigned long ssleay_value; - sub[2]='\0'; - sub[1]='\0'; - ssleay_value = OpenSSL_version_num(); - if(ssleay_value&0xff0) { - int minor_ver = (ssleay_value >> 4) & 0xff; - if(minor_ver > 26) { - /* handle extended version introduced for 0.9.8za */ - sub[1] = (char) ((minor_ver - 1) % 26 + 'a' + 1); - sub[0] = 'z'; - } - else { - sub[0] = (char) (minor_ver + 'a' - 1); - } - } - else - sub[0]='\0'; - - return curl_msnprintf(buffer, size, "%s/%lx.%lx.%lx%s" -#ifdef OPENSSL_FIPS - "-fips" -#endif - , - OSSL_PACKAGE, - (ssleay_value >> 28) & 0xf, - (ssleay_value >> 20) & 0xff, - (ssleay_value >> 12) & 0xff, - sub); #endif } @@ -5851,7 +5429,7 @@ const struct Curl_ssl Curl_ssl_openssl = { #ifdef HAVE_SSL_CTX_SET1_SIGALGS SSLSUPP_SIGNATURE_ALGORITHMS | #endif -#ifdef USE_ECH_OPENSSL +#ifdef HAVE_SSL_SET1_ECH_CONFIG_LIST SSLSUPP_ECH | #endif SSLSUPP_CA_CACHE | diff --git a/lib/vtls/openssl.h b/lib/vtls/openssl.h index 021d754a62b4..c3ba67a8ff41 100644 --- a/lib/vtls/openssl.h +++ b/lib/vtls/openssl.h @@ -51,8 +51,7 @@ * BoringSSL: supported since d28f59c27bac (committed 2015-11-19) * LibreSSL: not supported. 3.5.0+ has a stub function that does nothing. */ -#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && \ - !defined(LIBRESSL_VERSION_NUMBER)) || defined(HAVE_BORINGSSL_LIKE) +#ifndef LIBRESSL_VERSION_NUMBER #define HAVE_KEYLOG_CALLBACK #endif @@ -151,8 +150,7 @@ CURLcode Curl_ossl_check_peer_cert(struct Curl_cfilter *cf, struct ssl_peer *peer); /* Report properties of a successful handshake */ -void Curl_ossl_report_handshake(struct Curl_easy *data, - struct ossl_ctx *octx); +void Curl_ossl_report_handshake(struct Curl_easy *data, struct ossl_ctx *octx); #endif /* USE_OPENSSL */ #endif /* HEADER_CURL_SSLUSE_H */ diff --git a/lib/vtls/rustls.c b/lib/vtls/rustls.c index ff2dea82b606..014f11b4f0ec 100644 --- a/lib/vtls/rustls.c +++ b/lib/vtls/rustls.c @@ -31,10 +31,9 @@ #include #include "../curlx/fopen.h" -#include "../curlx/inet_pton.h" #include "../curlx/strerr.h" #include "../urldata.h" -#include "../sendf.h" +#include "../curl_trc.h" #include "vtls.h" #include "vtls_int.h" #include "rustls.h" @@ -42,12 +41,7 @@ #include "cipher_suite.h" #include "x509asn1.h" -/* The last #include files should be: */ -#include "../curl_memory.h" -#include "../memdebug.h" - -struct rustls_ssl_backend_data -{ +struct rustls_ssl_backend_data { const struct rustls_client_config *config; struct rustls_connection *conn; size_t plain_out_buffered; @@ -62,17 +56,17 @@ static CURLcode map_error(const rustls_result r) return CURLE_PEER_FAILED_VERIFICATION; } switch(r) { - case RUSTLS_RESULT_OK: - return CURLE_OK; - case RUSTLS_RESULT_NULL_PARAMETER: - return CURLE_BAD_FUNCTION_ARGUMENT; - default: - return CURLE_RECV_ERROR; + case RUSTLS_RESULT_OK: + return CURLE_OK; + case RUSTLS_RESULT_NULL_PARAMETER: + return CURLE_BAD_FUNCTION_ARGUMENT; + default: + return CURLE_RECV_ERROR; } } -static void -rustls_failf(struct Curl_easy *data, const rustls_result rr, const char *msg) +static void rustls_failf(struct Curl_easy *data, const rustls_result rr, + const char *msg) { char errorbuf[STRERROR_LEN]; size_t errorlen; @@ -80,8 +74,8 @@ rustls_failf(struct Curl_easy *data, const rustls_result rr, const char *msg) failf(data, "%s: %.*s", msg, (int)errorlen, errorbuf); } -static bool -cr_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data) +static bool cr_data_pending(struct Curl_cfilter *cf, + const struct Curl_easy *data) { const struct ssl_connect_data *ctx = cf->ctx; struct rustls_ssl_backend_data *backend; @@ -97,11 +91,11 @@ struct io_ctx { struct Curl_easy *data; }; -static int -read_cb(void *userdata, uint8_t *buf, uintptr_t len, uintptr_t *out_n) +static int read_cb(void *userdata, uint8_t *buf, uintptr_t len, + uintptr_t *out_n) { const struct io_ctx *io_ctx = userdata; - struct ssl_connect_data *const connssl = io_ctx->cf->ctx; + struct ssl_connect_data * const connssl = io_ctx->cf->ctx; CURLcode result; int ret = 0; size_t nread; @@ -124,8 +118,8 @@ read_cb(void *userdata, uint8_t *buf, uintptr_t len, uintptr_t *out_n) return ret; } -static int -write_cb(void *userdata, const uint8_t *buf, uintptr_t len, uintptr_t *out_n) +static int write_cb(void *userdata, const uint8_t *buf, uintptr_t len, + uintptr_t *out_n) { const struct io_ctx *io_ctx = userdata; CURLcode result; @@ -133,7 +127,7 @@ write_cb(void *userdata, const uint8_t *buf, uintptr_t len, uintptr_t *out_n) size_t nwritten; result = Curl_conn_cf_send(io_ctx->cf->next, io_ctx->data, - (const char *)buf, len, FALSE, &nwritten); + buf, len, FALSE, &nwritten); if(result) { nwritten = 0; if(CURLE_AGAIN == result) @@ -150,8 +144,8 @@ write_cb(void *userdata, const uint8_t *buf, uintptr_t len, uintptr_t *out_n) static ssize_t tls_recv_more(struct Curl_cfilter *cf, struct Curl_easy *data, CURLcode *err) { - const struct ssl_connect_data *const connssl = cf->ctx; - struct rustls_ssl_backend_data *const backend = + const struct ssl_connect_data * const connssl = cf->ctx; + struct rustls_ssl_backend_data * const backend = (struct rustls_ssl_backend_data *)connssl->backend; struct io_ctx io_ctx; size_t tls_bytes_read = 0; @@ -190,12 +184,11 @@ static ssize_t tls_recv_more(struct Curl_cfilter *cf, * Filter receive method implementation. `plainbuf` and `plainlen` * are always not NULL/0. */ -static CURLcode -cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data, - char *plainbuf, size_t plainlen, size_t *pnread) +static CURLcode cr_recv(struct Curl_cfilter *cf, struct Curl_easy *data, + char *plainbuf, size_t plainlen, size_t *pnread) { - const struct ssl_connect_data *const connssl = cf->ctx; - struct rustls_ssl_backend_data *const backend = + const 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; CURLcode result = CURLE_OK; @@ -304,12 +297,12 @@ static CURLcode cr_flush_out(struct Curl_cfilter *cf, struct Curl_easy *data, * In that case, it will not read anything into Rustls' plaintext input buffer. * It will only drain Rustls' plaintext output buffer into the socket. */ -static CURLcode -cr_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *plainbuf, size_t plainlen, size_t *pnwritten) +static CURLcode cr_send(struct Curl_cfilter *cf, struct Curl_easy *data, + const void *plainbuf, size_t plainlen, + size_t *pnwritten) { - const struct ssl_connect_data *const connssl = cf->ctx; - struct rustls_ssl_backend_data *const backend = + const 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; size_t plainwritten = 0; @@ -383,18 +376,15 @@ cr_send(struct Curl_cfilter *cf, struct Curl_easy *data, /* A server certificate verify callback for Rustls that always returns RUSTLS_RESULT_OK, or in other words disable certificate verification. */ -static uint32_t -cr_verify_none(void *userdata, - const rustls_verify_server_cert_params *params) +static uint32_t cr_verify_none(void *userdata, + const rustls_verify_server_cert_params *params) { (void)userdata; (void)params; return RUSTLS_RESULT_OK; } -static int -read_file_into(const char *filename, - struct dynbuf *out) +static int read_file_into(const char *filename, struct dynbuf *out) { FILE *f = curlx_fopen(filename, FOPEN_READTEXT); if(!f) { @@ -404,8 +394,8 @@ read_file_into(const char *filename, for(;;) { uint8_t buf[256]; const size_t rr = fread(buf, 1, sizeof(buf), f); - if(rr == 0 || - CURLE_OK != curlx_dyn_addn(out, buf, rr)) { + if((!rr && !feof(f)) || + curlx_dyn_addn(out, buf, rr)) { curlx_fclose(f); return 0; } @@ -468,16 +458,17 @@ cr_get_selected_ciphers(struct Curl_easy *data, if(!id) { if(ptr[0] != '\0') infof(data, "rustls: unknown cipher in list: \"%.*s\"", - (int) (end - ptr), ptr); + (int)(end - ptr), ptr); continue; } /* No duplicates allowed (so selected cannot overflow) */ - for(i = 0; i < count && selected[i] != entry; i++); + for(i = 0; i < count && selected[i] != entry; i++) + ; if(i < count) { if(i >= default13_count) infof(data, "rustls: duplicate cipher in list: \"%.*s\"", - (int) (end - ptr), ptr); + (int)(end - ptr), ptr); continue; } @@ -494,11 +485,12 @@ cr_get_selected_ciphers(struct Curl_easy *data, for(j = 0; j < default_len; j++) { entry = rustls_default_crypto_provider_ciphersuites_get(j); if(rustls_supported_ciphersuite_protocol_version(entry) == - RUSTLS_TLS_VERSION_TLSV1_3) + RUSTLS_TLS_VERSION_TLSV1_3) continue; /* No duplicates allowed (so selected cannot overflow) */ - for(i = 0; i < count && selected[i] != entry; i++); + for(i = 0; i < count && selected[i] != entry; i++) + ; if(i < count) continue; @@ -509,16 +501,16 @@ cr_get_selected_ciphers(struct Curl_easy *data, *selected_size = count; } -static void -cr_keylog_log_cb(struct rustls_str label, - const uint8_t *client_random, size_t client_random_len, - const uint8_t *secret, size_t secret_len) +static void cr_keylog_log_cb(struct rustls_str label, + const uint8_t *client_random, + size_t client_random_len, const uint8_t *secret, + size_t secret_len) { char clabel[KEYLOG_LABEL_MAXLEN]; (void)client_random_len; DEBUGASSERT(client_random_len == CLIENT_RANDOM_SIZE); /* Turning a "rustls_str" into a null delimited "c" string */ - curl_msnprintf(clabel, label.len + 1, "%.*s", (int)label.len, label.data); + curl_msnprintf(clabel, sizeof(clabel), "%.*s", (int)label.len, label.data); Curl_tls_keylog_write(clabel, client_random, secret, secret_len); } @@ -532,12 +524,11 @@ init_config_builder(struct Curl_easy *data, const struct rustls_crypto_provider *custom_provider = NULL; uint16_t tls_versions[2] = { - RUSTLS_TLS_VERSION_TLSV1_2, - RUSTLS_TLS_VERSION_TLSV1_3, + RUSTLS_TLS_VERSION_TLSV1_2, + RUSTLS_TLS_VERSION_TLSV1_3, }; size_t tls_versions_len = 2; - size_t cipher_suites_len = - rustls_default_crypto_provider_ciphersuites_len(); + size_t cipher_suites_len = rustls_default_crypto_provider_ciphersuites_len(); CURLcode result = CURLE_OK; rustls_result rr; @@ -586,7 +577,7 @@ init_config_builder(struct Curl_easy *data, } #endif /* USE_ECH */ - cipher_suites = malloc(sizeof(cipher_suites) * (cipher_suites_len)); + cipher_suites = curlx_malloc(sizeof(*cipher_suites) * (cipher_suites_len)); if(!cipher_suites) { result = CURLE_OUT_OF_MEMORY; goto cleanup; @@ -606,7 +597,7 @@ init_config_builder(struct Curl_easy *data, &custom_provider_builder); if(rr != RUSTLS_RESULT_OK) { rustls_failf(data, rr, - "failed to create crypto provider builder from default"); + "failed to create crypto provider builder from default"); result = CURLE_SSL_CIPHER; goto cleanup; } @@ -618,13 +609,13 @@ init_config_builder(struct Curl_easy *data, cipher_suites_len); if(rr != RUSTLS_RESULT_OK) { rustls_failf(data, rr, - "failed to set ciphersuites for crypto provider builder"); + "failed to set ciphersuites for crypto provider builder"); result = CURLE_SSL_CIPHER; goto cleanup; } - rr = rustls_crypto_provider_builder_build( - custom_provider_builder, &custom_provider); + rr = rustls_crypto_provider_builder_build(custom_provider_builder, + &custom_provider); if(rr != RUSTLS_RESULT_OK) { rustls_failf(data, rr, "failed to build custom crypto provider"); result = CURLE_SSL_CIPHER; @@ -632,9 +623,9 @@ init_config_builder(struct Curl_easy *data, } rr = rustls_client_config_builder_new_custom(custom_provider, - tls_versions, - tls_versions_len, - config_builder); + tls_versions, + tls_versions_len, + config_builder); if(rr != RUSTLS_RESULT_OK) { rustls_failf(data, rr, "failed to create client config builder"); result = CURLE_SSL_CIPHER; @@ -643,7 +634,7 @@ init_config_builder(struct Curl_easy *data, cleanup: if(cipher_suites) { - free(cipher_suites); + curlx_free(cipher_suites); } if(custom_provider_builder) { rustls_crypto_provider_builder_free(custom_provider_builder); @@ -657,7 +648,8 @@ init_config_builder(struct Curl_easy *data, static void init_config_builder_alpn(struct Curl_easy *data, const struct ssl_connect_data *connssl, - struct rustls_client_config_builder *config_builder) { + struct rustls_client_config_builder *config_builder) +{ struct alpn_proto_buf proto; rustls_slice_bytes alpn[ALPN_ENTRIES_MAX]; size_t i; @@ -672,8 +664,7 @@ init_config_builder_alpn(struct Curl_easy *data, infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data); } -static CURLcode -init_config_builder_verifier_crl( +static CURLcode init_config_builder_verifier_crl( struct Curl_easy *data, const struct ssl_primary_config *conn_config, struct rustls_web_pki_server_cert_verifier_builder *builder) @@ -709,7 +700,8 @@ init_config_builder_verifier(struct Curl_easy *data, struct rustls_client_config_builder *builder, const struct ssl_primary_config *conn_config, const struct curl_blob *ca_info_blob, - const char * const ssl_cafile) { + const char * const ssl_cafile) +{ const struct rustls_root_cert_store *roots = NULL; struct rustls_root_cert_store_builder *roots_builder = NULL; struct rustls_web_pki_server_cert_verifier_builder *verifier_builder = NULL; @@ -725,7 +717,6 @@ init_config_builder_verifier(struct Curl_easy *data, 1); if(rr != RUSTLS_RESULT_OK) { rustls_failf(data, rr, "failed to parse trusted certificates from blob"); - result = CURLE_SSL_CACERT_BADFILE; goto cleanup; } @@ -736,7 +727,6 @@ init_config_builder_verifier(struct Curl_easy *data, 1); if(rr != RUSTLS_RESULT_OK) { rustls_failf(data, rr, "failed to load trusted certificates"); - result = CURLE_SSL_CACERT_BADFILE; goto cleanup; } @@ -746,15 +736,20 @@ init_config_builder_verifier(struct Curl_easy *data, if(rr != RUSTLS_RESULT_OK) { rustls_failf(data, rr, "failed to build trusted root certificate store"); result = CURLE_SSL_CACERT_BADFILE; + goto cleanup; } verifier_builder = rustls_web_pki_server_cert_verifier_builder_new(roots); + if(!verifier_builder) { + result = CURLE_OUT_OF_MEMORY; + goto cleanup; + } if(conn_config->CRLfile) { result = init_config_builder_verifier_crl(data, - conn_config, - verifier_builder); - if(result != CURLE_OK) { + conn_config, + verifier_builder); + if(result) { goto cleanup; } } @@ -786,8 +781,7 @@ init_config_builder_verifier(struct Curl_easy *data, return result; } -static CURLcode -init_config_builder_platform_verifier( +static CURLcode init_config_builder_platform_verifier( struct Curl_easy *data, struct rustls_client_config_builder *builder) { @@ -887,10 +881,8 @@ init_config_builder_client_auth(struct Curl_easy *data, rr = rustls_certified_key_keys_match(certified_key); if(rr != RUSTLS_RESULT_OK) { - rustls_failf(data, - rr, + rustls_failf(data, rr, "rustls: client certificate and keypair files do not match:"); - result = CURLE_SSL_CERTPROBLEM; goto cleanup; } @@ -999,7 +991,7 @@ init_config_builder_ech(struct Curl_easy *data, cleanup: /* if we base64 decoded, we can free now */ if(data->set.tls_ech & CURLECH_CLA_CFG && data->set.str[STRING_ECH_CONFIG]) { - free(ech_config); + curlx_free(ech_config); } if(dns) { Curl_resolv_unlink(data, &dns); @@ -1008,9 +1000,9 @@ init_config_builder_ech(struct Curl_easy *data, } #endif /* USE_ECH */ -static CURLcode -cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data, - struct rustls_ssl_backend_data *const backend) +static CURLcode cr_init_backend(struct Curl_cfilter *cf, + struct Curl_easy *data, + struct rustls_ssl_backend_data * const backend) { const struct ssl_connect_data *connssl = cf->ctx; const struct ssl_primary_config *conn_config = @@ -1088,13 +1080,9 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data, return result; } - rr = rustls_client_config_builder_build( - config_builder, - &backend->config); + rr = rustls_client_config_builder_build(config_builder, &backend->config); if(rr != RUSTLS_RESULT_OK) { rustls_failf(data, rr, "failed to build client config"); - rustls_client_config_builder_free(config_builder); - rustls_client_config_free(backend->config); return CURLE_SSL_CONNECT_ERROR; } @@ -1104,6 +1092,8 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data, &rconn); if(rr != RUSTLS_RESULT_OK) { rustls_failf(data, rr, "rustls_client_connection_new"); + rustls_client_config_free(backend->config); + backend->config = NULL; return CURLE_COULDNT_CONNECT; } DEBUGASSERT(rconn); @@ -1113,11 +1103,11 @@ cr_init_backend(struct Curl_cfilter *cf, struct Curl_easy *data, return result; } -static void -cr_set_negotiated_alpn(struct Curl_cfilter *cf, struct Curl_easy *data, - const struct rustls_connection *rconn) +static void cr_set_negotiated_alpn(struct Curl_cfilter *cf, + struct Curl_easy *data, + const struct rustls_connection *rconn) { - struct ssl_connect_data *const connssl = cf->ctx; + struct ssl_connect_data * const connssl = cf->ctx; const uint8_t *protocol = NULL; size_t len = 0; @@ -1130,12 +1120,11 @@ cr_set_negotiated_alpn(struct Curl_cfilter *cf, struct Curl_easy *data, * This function will set `*done` to true once the handshake is complete. * This function never reads the value of `*done*`. */ -static CURLcode -cr_connect(struct Curl_cfilter *cf, - struct Curl_easy *data, bool *done) +static CURLcode cr_connect(struct Curl_cfilter *cf, struct Curl_easy *data, + bool *done) { - struct ssl_connect_data *const connssl = cf->ctx; - const struct rustls_ssl_backend_data *const backend = + struct ssl_connect_data * const connssl = cf->ctx; + const struct rustls_ssl_backend_data * const backend = (struct rustls_ssl_backend_data *)connssl->backend; const struct rustls_connection *rconn = NULL; CURLcode tmperr = CURLE_OK; @@ -1162,9 +1151,9 @@ cr_connect(struct Curl_cfilter *cf, /* Read/write data until the handshake is done or the socket would block. */ for(;;) { /* - * Connection has been established according to Rustls. Set send/recv - * handlers, and update the state machine. - */ + * Connection has been established according to Rustls. Set send/recv + * handlers, and update the state machine. + */ connssl->io_need = CURL_SSL_IO_NEED_NONE; if(!rustls_connection_is_handshaking(rconn)) { /* Rustls claims it is no longer handshaking *before* it has @@ -1183,8 +1172,7 @@ cr_connect(struct Curl_cfilter *cf, } /* REALLY Done with the handshake. */ { - const uint16_t proto = - rustls_connection_get_protocol_version(rconn); + const uint16_t proto = rustls_connection_get_protocol_version(rconn); const rustls_str ciphersuite_name = rustls_connection_get_negotiated_ciphersuite_name(rconn); const rustls_str kex_group_name = @@ -1206,8 +1194,13 @@ cr_connect(struct Curl_cfilter *cf, if(data->set.ssl.certinfo) { size_t num_certs = 0; size_t i; - while(rustls_connection_get_peer_certificate(rconn, (int)num_certs)) { + while(rustls_connection_get_peer_certificate(rconn, num_certs)) { num_certs++; + if(num_certs > MAX_ALLOWED_CERT_AMOUNT) { + failf(data, "%zu certificates is more than allowed (%u)", + num_certs, MAX_ALLOWED_CERT_AMOUNT); + return CURLE_SSL_CONNECT_ERROR; + } } result = Curl_ssl_init_certinfo(data, (int)num_certs); if(result) @@ -1289,9 +1282,7 @@ cr_connect(struct Curl_cfilter *cf, DEBUGASSERT(FALSE); } -static void * -cr_get_internals(struct ssl_connect_data *connssl, - CURLINFO info) +static void *cr_get_internals(struct ssl_connect_data *connssl, CURLINFO info) { struct rustls_ssl_backend_data *backend = (struct rustls_ssl_backend_data *)connssl->backend; @@ -1300,10 +1291,8 @@ cr_get_internals(struct ssl_connect_data *connssl, return backend->conn; } -static CURLcode -cr_shutdown(struct Curl_cfilter *cf, - struct Curl_easy *data, - const bool send_shutdown, bool *done) +static CURLcode cr_shutdown(struct Curl_cfilter *cf, struct Curl_easy *data, + const bool send_shutdown, bool *done) { struct ssl_connect_data *connssl = cf->ctx; struct rustls_ssl_backend_data *backend = @@ -1365,8 +1354,7 @@ cr_shutdown(struct Curl_cfilter *cf, return result; } -static void -cr_close(struct Curl_cfilter *cf, struct Curl_easy *data) +static void cr_close(struct Curl_cfilter *cf, struct Curl_easy *data) { const struct ssl_connect_data *connssl = cf->ctx; struct rustls_ssl_backend_data *backend = @@ -1390,13 +1378,12 @@ static size_t cr_version(char *buffer, size_t size) return curl_msnprintf(buffer, size, "%.*s", (int)ver.len, ver.data); } -static CURLcode -cr_random(struct Curl_easy *data, unsigned char *entropy, size_t length) +static CURLcode cr_random(struct Curl_easy *data, unsigned char *entropy, + size_t length) { rustls_result rresult = 0; (void)data; - rresult = - rustls_default_crypto_provider_random(entropy, length); + rresult = rustls_default_crypto_provider_random(entropy, length); return map_error(rresult); } diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c index ae5834d84342..2575a9f8f97a 100644 --- a/lib/vtls/schannel.c +++ b/lib/vtls/schannel.c @@ -34,7 +34,7 @@ #ifdef USE_SCHANNEL #ifndef USE_WINDOWS_SSPI -# error "cannot compile SCHANNEL support without SSPI." +#error "cannot compile SCHANNEL support without SSPI." #endif #include "schannel.h" @@ -42,26 +42,20 @@ #include "vtls.h" #include "vtls_int.h" #include "vtls_scache.h" -#include "../sendf.h" +#include "../curl_trc.h" #include "../connect.h" /* for the connect timeout */ #include "../strdup.h" #include "../strerror.h" #include "../select.h" /* for the socket readiness */ #include "../curlx/fopen.h" -#include "../curlx/inet_pton.h" /* for IP addr SNI check */ #include "../curlx/multibyte.h" -#include "../curlx/warnless.h" #include "x509asn1.h" -#include "../multiif.h" #include "../system_win32.h" #include "../curlx/version_win32.h" #include "../rand.h" #include "../curlx/strparse.h" #include "../progress.h" - -/* The last #include file should be: */ -#include "../curl_memory.h" -#include "../memdebug.h" +#include "../curl_sha256.h" /* Some verbose debug messages are wrapped by SCH_DEV() instead of DEBUGF() * and only shown if CURL_SCHANNEL_DEV_DEBUG was defined at build time. These @@ -70,11 +64,11 @@ */ #ifdef CURL_SCHANNEL_DEV_DEBUG #define SCH_DEV(x) x -#define SCH_DEV_SHOWBOOL(x) \ +#define SCH_DEV_SHOWBOOL(x) \ infof(data, "schannel: " #x " %s", (x) ? "TRUE" : "FALSE"); #else -#define SCH_DEV(x) do { } while(0) -#define SCH_DEV_SHOWBOOL(x) do { } while(0) +#define SCH_DEV(x) do {} while(0) +#define SCH_DEV_SHOWBOOL(x) do {} while(0) #endif /* Offered by mingw-w64 v8+. MS SDK 7.0A+. */ @@ -118,12 +112,6 @@ #define CALG_SHA_256 0x0000800c #endif -/* Work around typo in CeGCC (as of 0.59.1) w32api headers */ -#if defined(__MINGW32CE__) && \ - !defined(ALG_CLASS_DHASH) && defined(ALG_CLASS_HASH) -#define ALG_CLASS_DHASH ALG_CLASS_HASH -#endif - /* Offered by mingw-w64 v4+. MS SDK 6.0A+. */ #ifndef PKCS12_NO_PERSIST_KEY #define PKCS12_NO_PERSIST_KEY 0x00008000 @@ -168,10 +156,9 @@ static void InitSecBufferDesc(SecBufferDesc *desc, SecBuffer *BufArr, desc->cBuffers = NumArrElem; } -static CURLcode -schannel_set_ssl_version_min_max(DWORD *enabled_protocols, - struct Curl_cfilter *cf, - struct Curl_easy *data) +static CURLcode schannel_set_ssl_version_min_max(DWORD *enabled_protocols, + struct Curl_cfilter *cf, + struct Curl_easy *data) { struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); long ssl_version = conn_config->version; @@ -231,7 +218,7 @@ struct algo { int id; }; -static const struct algo algs[]= { +static const struct algo algs[] = { CIPHEROPTION(CALG_MD2), CIPHEROPTION(CALG_MD4), CIPHEROPTION(CALG_MD5), @@ -339,8 +326,7 @@ static const struct algo algs[]= { {NULL, 0}, }; -static int -get_alg_id_by_name(const char *name) +static int get_alg_id_by_name(const char *name) { const char *nameEnd = strchr(name, ':'); size_t n = nameEnd ? (size_t)(nameEnd - name) : strlen(name); @@ -355,9 +341,8 @@ get_alg_id_by_name(const char *name) #define NUM_CIPHERS 47 /* There are 47 options listed above */ -static CURLcode -set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers, - ALG_ID *algIds) +static CURLcode set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers, + ALG_ID *algIds) { const char *startCur = ciphers; int algCount = 0; @@ -384,11 +369,9 @@ set_ssl_ciphers(SCHANNEL_CRED *schannel_cred, char *ciphers, return CURLE_OK; } -#ifndef UNDER_CE /* Function allocates memory for store_path only if CURLE_OK is returned */ -static CURLcode -get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path, - TCHAR **thumbprint) +static CURLcode get_cert_location(TCHAR *path, DWORD *store_name, + TCHAR **store_path, TCHAR **thumbprint) { TCHAR *sep; TCHAR *store_path_start; @@ -410,14 +393,11 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path, *store_name = CERT_SYSTEM_STORE_SERVICES; else if(_tcsncmp(path, TEXT("Users"), store_name_len) == 0) *store_name = CERT_SYSTEM_STORE_USERS; - else if(_tcsncmp(path, TEXT("CurrentUserGroupPolicy"), - store_name_len) == 0) + else if(_tcsncmp(path, TEXT("CurrentUserGroupPolicy"), store_name_len) == 0) *store_name = CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY; - else if(_tcsncmp(path, TEXT("LocalMachineGroupPolicy"), - store_name_len) == 0) + else if(_tcsncmp(path, TEXT("LocalMachineGroupPolicy"), store_name_len) == 0) *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY; - else if(_tcsncmp(path, TEXT("LocalMachineEnterprise"), - store_name_len) == 0) + else if(_tcsncmp(path, TEXT("LocalMachineEnterprise"), store_name_len) == 0) *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE; else return CURLE_SSL_CERTPROBLEM; @@ -433,18 +413,16 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path, return CURLE_SSL_CERTPROBLEM; *sep = TEXT('\0'); - *store_path = Curl_tcsdup(store_path_start); + *store_path = curlx_tcsdup(store_path_start); *sep = TEXT('\\'); if(!*store_path) return CURLE_OUT_OF_MEMORY; return CURLE_OK; } -#endif -static CURLcode -schannel_acquire_credential_handle(struct Curl_cfilter *cf, - struct Curl_easy *data) +static CURLcode schannel_acquire_credential_handle(struct Curl_cfilter *cf, + struct Curl_easy *data) { struct ssl_connect_data *connssl = cf->ctx; struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); @@ -472,37 +450,36 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf, if(ssl_config->no_revoke) { flags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK | - SCH_CRED_IGNORE_REVOCATION_OFFLINE; + SCH_CRED_IGNORE_REVOCATION_OFFLINE; DEBUGF(infof(data, "schannel: disabled server certificate revocation " - "checks")); + "checks")); } else if(ssl_config->revoke_best_effort) { flags |= SCH_CRED_IGNORE_NO_REVOCATION_CHECK | - SCH_CRED_IGNORE_REVOCATION_OFFLINE | SCH_CRED_REVOCATION_CHECK_CHAIN; + SCH_CRED_IGNORE_REVOCATION_OFFLINE | + SCH_CRED_REVOCATION_CHECK_CHAIN; DEBUGF(infof(data, "schannel: ignore revocation offline errors")); } else { flags |= SCH_CRED_REVOCATION_CHECK_CHAIN; - DEBUGF(infof(data, - "schannel: checking server certificate revocation")); + DEBUGF(infof(data, "schannel: checking server certificate revocation")); } } else { flags = SCH_CRED_MANUAL_CRED_VALIDATION | - SCH_CRED_IGNORE_NO_REVOCATION_CHECK | - SCH_CRED_IGNORE_REVOCATION_OFFLINE; - DEBUGF(infof(data, - "schannel: disabled server cert revocation checks")); + SCH_CRED_IGNORE_NO_REVOCATION_CHECK | + SCH_CRED_IGNORE_REVOCATION_OFFLINE; + DEBUGF(infof(data, "schannel: disabled server cert revocation checks")); } if(!conn_config->verifyhost) { flags |= SCH_CRED_NO_SERVERNAME_CHECK; DEBUGF(infof(data, "schannel: verifyhost setting prevents Schannel from " - "comparing the supplied target name with the subject " - "names in server certificates.")); + "comparing the supplied target name with the subject " + "names in server certificates.")); } if(!ssl_config->auto_client_cert) { @@ -519,8 +496,7 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf, case CURL_SSLVERSION_TLSv1_0: case CURL_SSLVERSION_TLSv1_1: case CURL_SSLVERSION_TLSv1_2: - case CURL_SSLVERSION_TLSv1_3: - { + case CURL_SSLVERSION_TLSv1_3: { result = schannel_set_ssl_version_min_max(&enabled_protocols, cf, data); if(result) return result; @@ -535,7 +511,6 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf, return CURLE_SSL_CONNECT_ERROR; } -#ifndef UNDER_CE /* client certificate */ if(data->set.ssl.primary.clientcert || data->set.ssl.primary.cert_blob) { DWORD cert_store_name = 0; @@ -562,24 +537,27 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf, result = get_cert_location(cert_path, &cert_store_name, &cert_store_path, &cert_thumbprint_str); - if(result && (data->set.ssl.primary.clientcert[0]!='\0')) + if(result && (data->set.ssl.primary.clientcert[0] != '\0')) fInCert = curlx_fopen(data->set.ssl.primary.clientcert, "rb"); if(result && !fInCert) { failf(data, "schannel: Failed to get certificate location" " or file for %s", data->set.ssl.primary.clientcert); - curlx_unicodefree(cert_path); + curlx_free(cert_path); return result; } } - if((fInCert || blob) && (data->set.ssl.cert_type) && - (!curl_strequal(data->set.ssl.cert_type, "P12"))) { + if((fInCert || blob) && data->set.ssl.cert_type && + !curl_strequal(data->set.ssl.cert_type, "P12")) { failf(data, "schannel: certificate format compatibility error " " for %s", blob ? "(memory blob)" : data->set.ssl.primary.clientcert); - curlx_unicodefree(cert_path); + curlx_free(cert_store_path); + curlx_free(cert_path); + if(fInCert) + curlx_fclose(fInCert); return CURLE_SSL_CERTPROBLEM; } @@ -588,13 +566,14 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf, https://learn.microsoft.com/archive/msdn-technet-forums/3e7bc95f-b21a-4bcd-bd2c-7f996718cae5 */ CRYPT_DATA_BLOB datablob; - WCHAR* pszPassword; + WCHAR *pszPassword; size_t pwd_len = 0; int str_w_len = 0; int cert_find_flags; const char *cert_showfilename_error = blob ? "(memory blob)" : data->set.ssl.primary.clientcert; - curlx_unicodefree(cert_path); + curlx_free(cert_store_path); + curlx_free(cert_path); if(fInCert) { long cert_tell = 0; bool continue_reading = fseek(fInCert, 0, SEEK_END) == 0; @@ -606,8 +585,8 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf, certsize = (size_t)cert_tell; if(continue_reading) continue_reading = fseek(fInCert, 0, SEEK_SET) == 0; - if(continue_reading) - certdata = malloc(certsize + 1); + if(continue_reading && (certsize < CURL_MAX_INPUT_LENGTH)) + certdata = curlx_malloc(certsize + 1); if((!certdata) || ((int) fread(certdata, certsize, 1, fInCert) != 1)) continue_reading = FALSE; @@ -615,18 +594,18 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf, if(!continue_reading) { failf(data, "schannel: Failed to read cert file %s", data->set.ssl.primary.clientcert); - free(certdata); + curlx_free(certdata); return CURLE_SSL_CERTPROBLEM; } } /* Convert key-pair data to the in-memory certificate store */ - datablob.pbData = (BYTE*)certdata; + datablob.pbData = (BYTE *)certdata; datablob.cbData = (DWORD)certsize; if(data->set.ssl.key_passwd) pwd_len = strlen(data->set.ssl.key_passwd); - pszPassword = (WCHAR*)malloc(sizeof(WCHAR)*(pwd_len + 1)); + pszPassword = (WCHAR *)curlx_malloc(sizeof(WCHAR) * (pwd_len + 1)); if(pszPassword) { if(pwd_len > 0) str_w_len = MultiByteToWideChar(CP_UTF8, @@ -646,10 +625,10 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf, else cert_store = PFXImportCertStore(&datablob, pszPassword, 0); - free(pszPassword); + curlx_free(pszPassword); } if(!blob) - free(certdata); + curlx_free(certdata); if(!cert_store) { DWORD errorcode = GetLastError(); if(errorcode == ERROR_INVALID_PASSWORD) @@ -703,12 +682,12 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf, cert_store_name, (path_utf8 ? path_utf8 : "(unknown)"), GetLastError()); - free(cert_store_path); - curlx_unicodefree(path_utf8); - curlx_unicodefree(cert_path); + curlx_free(cert_store_path); + curlx_free(path_utf8); + curlx_free(cert_path); return CURLE_SSL_CERTPROBLEM; } - free(cert_store_path); + curlx_free(cert_store_path); cert_thumbprint.pbData = cert_thumbprint_data; cert_thumbprint.cbData = CERT_THUMBPRINT_DATA_LEN; @@ -719,7 +698,7 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf, cert_thumbprint_data, &cert_thumbprint.cbData, NULL, NULL)) { - curlx_unicodefree(cert_path); + curlx_free(cert_path); CertCloseStore(cert_store, 0); return CURLE_SSL_CERTPROBLEM; } @@ -728,7 +707,7 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf, cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_HASH, &cert_thumbprint, NULL); - curlx_unicodefree(cert_path); + curlx_free(cert_path); if(!client_certs[0]) { /* CRYPT_E_NOT_FOUND / E_INVALIDARG */ @@ -739,11 +718,10 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf, } client_cert_store = cert_store; } -#endif /* allocate memory for the reusable credential handle */ backend->cred = (struct Curl_schannel_cred *) - calloc(1, sizeof(struct Curl_schannel_cred)); + curlx_calloc(1, sizeof(struct Curl_schannel_cred)); if(!backend->cred) { failf(data, "schannel: unable to allocate memory"); @@ -818,6 +796,8 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf, result = set_ssl_ciphers(&schannel_cred, ciphers, algIds); if(result) { failf(data, "schannel: Failed setting algorithm cipher list"); + if(client_certs[0]) + CertFreeCertificateContext(client_certs[0]); return result; } } @@ -845,7 +825,6 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf, char buffer[STRERROR_LEN]; failf(data, "schannel: AcquireCredentialsHandle failed: %s", Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); - Curl_safefree(backend->cred); switch(sspi_status) { case SEC_E_INSUFFICIENT_MEMORY: return CURLE_OUT_OF_MEMORY; @@ -862,16 +841,14 @@ schannel_acquire_credential_handle(struct Curl_cfilter *cf, return CURLE_OK; } -static CURLcode -schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) +static CURLcode schannel_connect_step1(struct Curl_cfilter *cf, + struct Curl_easy *data) { size_t written = 0; struct ssl_connect_data *connssl = cf->ctx; struct schannel_ssl_backend_data *backend = (struct schannel_ssl_backend_data *)connssl->backend; -#ifndef UNDER_CE struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); -#endif struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); SecBuffer outbuf; SecBufferDesc outbuf_desc; @@ -884,8 +861,7 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) CURLcode result; DEBUGASSERT(backend); - DEBUGF(infof(data, - "schannel: SSL/TLS connection with %s port %d (step 1/3)", + DEBUGF(infof(data, "schannel: SSL/TLS connection with %s port %d (step 1/3)", connssl->peer.hostname, connssl->peer.port)); if(curlx_verify_windows_version(5, 1, 0, PLATFORM_WINNT, @@ -902,11 +878,6 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) backend->use_alpn = FALSE; #endif -#ifdef UNDER_CE - /* certificate validation on Windows CE does not seem to work right; we will - * do it following a more manual process. */ - backend->use_manual_cred_validation = TRUE; -#else if(conn_config->CAfile || conn_config->ca_info_blob) { if(curlx_verify_windows_version(6, 1, 0, PLATFORM_WINNT, VERSION_GREATER_THAN_EQUAL)) { @@ -914,18 +885,17 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) } else { failf(data, "schannel: this version of Windows is too old to support " - "certificate verification via CA bundle file."); + "certificate verification via CA bundle file."); return CURLE_SSL_CACERT_BADFILE; } } else backend->use_manual_cred_validation = FALSE; -#endif backend->cred = NULL; /* check for an existing reusable credential handle */ - if(ssl_config->primary.cache_session) { + if(Curl_ssl_scache_use(cf, data)) { struct Curl_schannel_cred *old_cred; Curl_ssl_scache_lock(data); old_cred = Curl_ssl_scache_get_obj(cf, data, connssl->peer.scache_key); @@ -968,7 +938,7 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) int cur = 0; int list_start_index = 0; unsigned int *extension_len = NULL; - unsigned short* list_len = NULL; + unsigned short *list_len = NULL; struct alpn_proto_buf proto; /* The first four bytes will be an unsigned int indicating number @@ -984,7 +954,7 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) /* The next two bytes will be an unsigned short indicating the number of bytes used to list the preferred protocols. */ - list_len = (unsigned short*)(void *)(&alpn_buffer[cur]); + list_len = (unsigned short *)(void *)(&alpn_buffer[cur]); cur += (int)sizeof(unsigned short); list_start_index = cur; @@ -1022,8 +992,8 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) /* security request flags */ backend->req_flags = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | - ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY | - ISC_REQ_STREAM; + ISC_REQ_CONFIDENTIALITY | ISC_REQ_ALLOCATE_MEMORY | + ISC_REQ_STREAM; if(!ssl_config->auto_client_cert) { backend->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS; @@ -1031,7 +1001,7 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) /* allocate memory for the security context handle */ backend->ctxt = (struct Curl_schannel_ctxt *) - calloc(1, sizeof(struct Curl_schannel_ctxt)); + curlx_calloc(1, sizeof(struct Curl_schannel_ctxt)); if(!backend->ctxt) { failf(data, "schannel: unable to allocate memory"); return CURLE_OUT_OF_MEMORY; @@ -1086,7 +1056,8 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) /* send initial handshake data which is now stored in output buffer */ result = Curl_conn_cf_send(cf->next, data, - outbuf.pvBuffer, outbuf.cbBuffer, FALSE, + (const uint8_t *)outbuf.pvBuffer, + outbuf.cbBuffer, FALSE, &written); Curl_pSecFn->FreeContextBuffer(outbuf.pvBuffer); if(result || (outbuf.cbBuffer != written)) { @@ -1111,8 +1082,43 @@ schannel_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) return CURLE_OK; } -static CURLcode -schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) +static CURLcode schannel_error(struct Curl_easy *data, + SECURITY_STATUS sspi_status) +{ + char buffer[STRERROR_LEN]; + switch(sspi_status) { + case SEC_E_INSUFFICIENT_MEMORY: + failf(data, "schannel: next InitializeSecurityContext failed: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + return CURLE_OUT_OF_MEMORY; + case SEC_E_WRONG_PRINCIPAL: + failf(data, "schannel: SNI or certificate check failed: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + return CURLE_PEER_FAILED_VERIFICATION; + case SEC_E_UNTRUSTED_ROOT: + failf(data, "schannel: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + return CURLE_PEER_FAILED_VERIFICATION; +#if 0 + case SEC_E_INVALID_HANDLE: + case SEC_E_INVALID_TOKEN: + case SEC_E_LOGON_DENIED: + case SEC_E_TARGET_UNKNOWN: + case SEC_E_NO_AUTHENTICATING_AUTHORITY: + case SEC_E_INTERNAL_ERROR: + case SEC_E_NO_CREDENTIALS: + case SEC_E_UNSUPPORTED_FUNCTION: + case SEC_E_APPLICATION_PROTOCOL_MISMATCH: +#endif + default: + failf(data, "schannel: next InitializeSecurityContext failed: %s", + Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); + return CURLE_SSL_CONNECT_ERROR; + } +} + +static CURLcode schannel_connect_step2(struct Curl_cfilter *cf, + struct Curl_easy *data) { struct ssl_connect_data *connssl = cf->ctx; struct schannel_ssl_backend_data *backend = @@ -1135,8 +1141,7 @@ schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) doread = (connssl->io_need & CURL_SSL_IO_NEED_SEND) ? FALSE : TRUE; connssl->io_need = CURL_SSL_IO_NEED_NONE; - DEBUGF(infof(data, - "schannel: SSL/TLS connection with %s port %d (step 2/3)", + DEBUGF(infof(data, "schannel: SSL/TLS connection with %s port %d (step 2/3)", connssl->peer.hostname, connssl->peer.port)); if(!backend->cred || !backend->ctxt) @@ -1146,7 +1151,7 @@ schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) if(!backend->decdata_buffer) { backend->decdata_offset = 0; backend->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; - backend->decdata_buffer = malloc(backend->decdata_length); + backend->decdata_buffer = curlx_malloc(backend->decdata_length); if(!backend->decdata_buffer) { failf(data, "schannel: unable to allocate memory"); return CURLE_OUT_OF_MEMORY; @@ -1158,7 +1163,7 @@ schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) backend->encdata_is_incomplete = FALSE; backend->encdata_offset = 0; backend->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE; - backend->encdata_buffer = malloc(backend->encdata_length); + backend->encdata_buffer = curlx_malloc(backend->encdata_length); if(!backend->encdata_buffer) { failf(data, "schannel: unable to allocate memory"); return CURLE_OUT_OF_MEMORY; @@ -1171,8 +1176,8 @@ schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) /* increase internal encrypted data buffer */ size_t reallocated_length = backend->encdata_offset + CURL_SCHANNEL_BUFFER_FREE_SIZE; - reallocated_buffer = realloc(backend->encdata_buffer, - reallocated_length); + reallocated_buffer = curlx_realloc(backend->encdata_buffer, + reallocated_length); if(!reallocated_buffer) { failf(data, "schannel: unable to re-allocate memory"); @@ -1223,7 +1228,8 @@ schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) backend->encdata_offset, backend->encdata_length)); /* setup input buffers */ - InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, malloc(backend->encdata_offset), + InitSecBuffer(&inbuf[0], SECBUFFER_TOKEN, + curlx_malloc(backend->encdata_offset), curlx_uztoul(backend->encdata_offset)); InitSecBuffer(&inbuf[1], SECBUFFER_EMPTY, NULL, 0); InitSecBufferDesc(&inbuf_desc, inbuf, 2); @@ -1245,12 +1251,12 @@ schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) /* The socket must be writeable (or a poll error occurred) before we call InitializeSecurityContext to continue processing the received TLS - records. This is because that function is not idempotent and we don't + records. This is because that function is not idempotent and we do not support partial save/resume sending replies of handshake tokens. */ if(!SOCKET_WRITABLE(Curl_conn_cf_get_socket(cf, data), 0)) { SCH_DEV(infof(data, "schannel: handshake waiting for writeable socket")); connssl->io_need = CURL_SSL_IO_NEED_SEND; - free(inbuf[0].pvBuffer); + curlx_free(inbuf[0].pvBuffer); return CURLE_OK; } @@ -1264,28 +1270,18 @@ schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) Curl_safefree(inbuf[0].pvBuffer); /* check if the handshake was incomplete */ - if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) { + switch(sspi_status) { + case SEC_E_INCOMPLETE_MESSAGE: backend->encdata_is_incomplete = TRUE; connssl->io_need = CURL_SSL_IO_NEED_RECV; DEBUGF(infof(data, "schannel: received incomplete message, need more data")); return CURLE_OK; - } - - /* If the server has requested a client certificate, attempt to continue - the handshake without one. This will allow connections to servers which - request a client certificate but do not require it. */ - if(sspi_status == SEC_I_INCOMPLETE_CREDENTIALS && - !(backend->req_flags & ISC_REQ_USE_SUPPLIED_CREDS)) { - backend->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS; - connssl->io_need = CURL_SSL_IO_NEED_SEND; - DEBUGF(infof(data, - "schannel: a client certificate has been requested")); - return CURLE_OK; - } - /* check if the handshake needs to be continued */ - if(sspi_status == SEC_I_CONTINUE_NEEDED || sspi_status == SEC_E_OK) { + case SEC_I_CONTINUE_NEEDED: + case SEC_E_OK: + /* check if the handshake needs to be continued */ + result = CURLE_OK; for(i = 0; i < 3; i++) { /* search for handshake tokens that need to be send */ if(outbuf[i].BufferType == SECBUFFER_TOKEN && outbuf[i].cbBuffer > 0) { @@ -1294,52 +1290,41 @@ schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) /* send handshake token to server */ result = Curl_conn_cf_send(cf->next, data, - outbuf[i].pvBuffer, outbuf[i].cbBuffer, + (const uint8_t *)outbuf[i].pvBuffer, + outbuf[i].cbBuffer, FALSE, &written); if(result || (outbuf[i].cbBuffer != written)) { failf(data, "schannel: failed to send next handshake data: " "sent %zu of %lu bytes", written, outbuf[i].cbBuffer); - return CURLE_SSL_CONNECT_ERROR; + result = CURLE_SSL_CONNECT_ERROR; } } - + } + for(i = 0; i < 3; i++) { /* free obsolete buffer */ - if(outbuf[i].pvBuffer) { + if(outbuf[i].pvBuffer) Curl_pSecFn->FreeContextBuffer(outbuf[i].pvBuffer); - } } - } - else { - char buffer[STRERROR_LEN]; - switch(sspi_status) { - case SEC_E_INSUFFICIENT_MEMORY: - failf(data, "schannel: next InitializeSecurityContext failed: %s", - Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); - return CURLE_OUT_OF_MEMORY; - case SEC_E_WRONG_PRINCIPAL: - failf(data, "schannel: SNI or certificate check failed: %s", - Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); - return CURLE_PEER_FAILED_VERIFICATION; - case SEC_E_UNTRUSTED_ROOT: - failf(data, "schannel: %s", - Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); - return CURLE_PEER_FAILED_VERIFICATION; -#if 0 - case SEC_E_INVALID_HANDLE: - case SEC_E_INVALID_TOKEN: - case SEC_E_LOGON_DENIED: - case SEC_E_TARGET_UNKNOWN: - case SEC_E_NO_AUTHENTICATING_AUTHORITY: - case SEC_E_INTERNAL_ERROR: - case SEC_E_NO_CREDENTIALS: - case SEC_E_UNSUPPORTED_FUNCTION: - case SEC_E_APPLICATION_PROTOCOL_MISMATCH: -#endif - default: - failf(data, "schannel: next InitializeSecurityContext failed: %s", - Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); - return CURLE_SSL_CONNECT_ERROR; + if(result) + return result; + break; + + case SEC_I_INCOMPLETE_CREDENTIALS: + if(!(backend->req_flags & ISC_REQ_USE_SUPPLIED_CREDS)) { + /* If the server has requested a client certificate, attempt to + continue the handshake without one. This will allow connections to + servers which request a client certificate but do not require + it. */ + backend->req_flags |= ISC_REQ_USE_SUPPLIED_CREDS; + connssl->io_need = CURL_SSL_IO_NEED_SEND; + DEBUGF(infof(data, + "schannel: a client certificate has been requested")); + return CURLE_OK; } + FALLTHROUGH(); + + default: + return schannel_error(data, sspi_status); } /* check if there was additional remaining encrypted data */ @@ -1361,7 +1346,8 @@ schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) if(backend->encdata_offset > inbuf[1].cbBuffer) { memmove(backend->encdata_buffer, (backend->encdata_buffer + backend->encdata_offset) - - inbuf[1].cbBuffer, inbuf[1].cbBuffer); + inbuf[1].cbBuffer, + inbuf[1].cbBuffer); backend->encdata_offset = inbuf[1].cbBuffer; if(sspi_status == SEC_I_CONTINUE_NEEDED) { doread = FALSE; @@ -1415,8 +1401,7 @@ schannel_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) return CURLE_OK; } -static bool -valid_cert_encoding(const CERT_CONTEXT *cert_context) +static bool valid_cert_encoding(const CERT_CONTEXT *cert_context) { return (cert_context != NULL) && ((cert_context->dwCertEncodingType & X509_ASN_ENCODING) != 0) && @@ -1424,12 +1409,11 @@ valid_cert_encoding(const CERT_CONTEXT *cert_context) (cert_context->cbCertEncoded > 0); } -typedef bool(*Read_crt_func)(const CERT_CONTEXT *ccert_context, - bool reverse_order, void *arg); +typedef bool (*Read_crt_func)(const CERT_CONTEXT *ccert_context, + bool reverse_order, void *arg); -static void -traverse_cert_store(const CERT_CONTEXT *context, Read_crt_func func, - void *arg) +static void traverse_cert_store(const CERT_CONTEXT *context, + Read_crt_func func, void *arg) { const CERT_CONTEXT *current_context = NULL; bool should_continue = TRUE; @@ -1454,32 +1438,31 @@ traverse_cert_store(const CERT_CONTEXT *context, Read_crt_func func, CertFreeCertificateContext(current_context); } -static bool -cert_counter_callback(const CERT_CONTEXT *ccert_context, bool reverse_order, - void *certs_count) +static bool cert_counter_callback(const CERT_CONTEXT *ccert_context, + bool reverse_order, void *certs_count) { (void)reverse_order; if(valid_cert_encoding(ccert_context)) (*(int *)certs_count)++; + if(*(int *)certs_count > MAX_ALLOWED_CERT_AMOUNT) + return FALSE; return TRUE; } -struct Adder_args -{ +struct Adder_args { struct Curl_easy *data; CURLcode result; int idx; int certs_count; }; -static bool -add_cert_to_certinfo(const CERT_CONTEXT *ccert_context, bool reverse_order, - void *raw_arg) +static bool add_cert_to_certinfo(const CERT_CONTEXT *ccert_context, + bool reverse_order, void *raw_arg) { - struct Adder_args *args = (struct Adder_args*)raw_arg; + struct Adder_args *args = (struct Adder_args *)raw_arg; args->result = CURLE_OK; if(valid_cert_encoding(ccert_context)) { - const char *beg = (const char *) ccert_context->pbCertEncoded; + const char *beg = (const char *)ccert_context->pbCertEncoded; const char *end = beg + ccert_context->cbCertEncoded; int insert_index = reverse_order ? (args->certs_count - 1) - args->idx : args->idx; @@ -1499,7 +1482,7 @@ static void schannel_session_free(void *sessionid) cred->refcount--; if(cred->refcount == 0) { Curl_pSecFn->FreeCredentialsHandle(&cred->cred_handle); - curlx_unicodefree(cred->sni_hostname); + curlx_free(cred->sni_hostname); if(cred->client_cert_store) { CertCloseStore(cred->client_cert_store, 0); cred->client_cert_store = NULL; @@ -1509,13 +1492,12 @@ static void schannel_session_free(void *sessionid) } } -static CURLcode -schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data) +static CURLcode schannel_connect_step3(struct Curl_cfilter *cf, + struct Curl_easy *data) { struct ssl_connect_data *connssl = cf->ctx; struct schannel_ssl_backend_data *backend = (struct schannel_ssl_backend_data *)connssl->backend; - struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); CURLcode result = CURLE_OK; SECURITY_STATUS sspi_status = SEC_E_OK; CERT_CONTEXT *ccert_context = NULL; @@ -1526,8 +1508,7 @@ schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data) DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); DEBUGASSERT(backend); - DEBUGF(infof(data, - "schannel: SSL/TLS connection with %s port %d (step 3/3)", + DEBUGF(infof(data, "schannel: SSL/TLS connection with %s port %d (step 3/3)", connssl->peer.hostname, connssl->peer.port)); if(!backend->cred) @@ -1583,7 +1564,7 @@ schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data) #endif /* save the current session data for possible reuse */ - if(ssl_config->primary.cache_session) { + if(Curl_ssl_scache_use(cf, data)) { Curl_ssl_scache_lock(data); /* Up ref count since call takes ownership */ backend->cred->refcount++; @@ -1607,6 +1588,12 @@ schannel_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data) } traverse_cert_store(ccert_context, cert_counter_callback, &certs_count); + if(certs_count > MAX_ALLOWED_CERT_AMOUNT) { + failf(data, "%d certificates is more than allowed (%u)", + certs_count, MAX_ALLOWED_CERT_AMOUNT); + CertFreeCertificateContext(ccert_context); + return CURLE_SSL_CONNECT_ERROR; + } result = Curl_ssl_init_certinfo(data, certs_count); if(!result) { @@ -1689,6 +1676,8 @@ enum schannel_renegotiate_caller_t { SCH_RENEG_CALLER_IS_SEND }; +#define MAX_RENEG_BLOCK_TIME (7 * 1000) /* 7 seconds in milliseconds */ + /* This function renegotiates the connection due to a server request received by schannel_recv. This function returns CURLE_AGAIN if the renegotiation is incomplete. In that case, we remain in the renegotiation (connecting) stage @@ -1700,7 +1689,6 @@ schannel_recv_renegotiate(struct Curl_cfilter *cf, struct Curl_easy *data, { CURLcode result; curl_socket_t sockfd; - const timediff_t max_renegotiate_ms = 5 * 60 * 1000; /* 5 minutes */ struct ssl_connect_data *connssl = cf->ctx; struct schannel_ssl_backend_data *backend = (struct schannel_ssl_backend_data *)connssl->backend; @@ -1710,15 +1698,11 @@ schannel_recv_renegotiate(struct Curl_cfilter *cf, struct Curl_easy *data, failf(data, "schannel: unexpected call to schannel_recv_renegotiate"); return CURLE_SSL_CONNECT_ERROR; } - + DEBUGASSERT(caller <= SCH_RENEG_CALLER_IS_SEND); if(caller == SCH_RENEG_CALLER_IS_RECV) SCH_DEV(infof(data, "schannel: renegotiation caller is schannel_recv")); - else if(caller == SCH_RENEG_CALLER_IS_SEND) + else SCH_DEV(infof(data, "schannel: renegotiation caller is schannel_send")); - else { - failf(data, "schannel: unknown caller for schannel_recv_renegotiate"); - return CURLE_SSL_CONNECT_ERROR; - } sockfd = Curl_conn_cf_get_socket(cf, data); @@ -1735,7 +1719,7 @@ schannel_recv_renegotiate(struct Curl_cfilter *cf, struct Curl_easy *data, connssl->connecting_state = ssl_connect_2; memset(rs, 0, sizeof(*rs)); rs->io_need = CURL_SSL_IO_NEED_SEND; - rs->start_time = curlx_now(); + rs->start_time = *Curl_pgrs_now(data); rs->started = TRUE; } @@ -1744,8 +1728,8 @@ schannel_recv_renegotiate(struct Curl_cfilter *cf, struct Curl_easy *data, curl_socket_t readfd, writefd; timediff_t elapsed; - elapsed = curlx_timediff(curlx_now(), rs->start_time); - if(elapsed >= max_renegotiate_ms) { + elapsed = curlx_ptimediff_ms(Curl_pgrs_now(data), &rs->start_time); + if(elapsed >= MAX_RENEG_BLOCK_TIME) { failf(data, "schannel: renegotiation timeout"); result = CURLE_SSL_CONNECT_ERROR; break; @@ -1786,7 +1770,7 @@ schannel_recv_renegotiate(struct Curl_cfilter *cf, struct Curl_easy *data, * data needs to be sent then we block for a writeable socket that should * be writeable immediately except for OS resource constraints. For caller * send if handshake data needs to be received then we block for a readable - * socket, which could take some time, but it's more likely the user has + * socket, which could take some time, but it is more likely the user has * called recv since they had called it prior (only recv can start * renegotiation and probably the user is going to call it again to get * more of their data before calling send). @@ -1804,47 +1788,46 @@ schannel_recv_renegotiate(struct Curl_cfilter *cf, struct Curl_easy *data, for(;;) { int what; - timediff_t timeout, remaining; + timediff_t timeout_ms, remaining; - if(Curl_pgrsUpdate(data)) { - result = CURLE_ABORTED_BY_CALLBACK; + result = Curl_pgrsUpdate(data); + if(result) break; - } - elapsed = curlx_timediff(curlx_now(), rs->start_time); - if(elapsed >= max_renegotiate_ms) { + elapsed = curlx_ptimediff_ms(Curl_pgrs_now(data), &rs->start_time); + if(elapsed >= MAX_RENEG_BLOCK_TIME) { failf(data, "schannel: renegotiation timeout"); result = CURLE_SSL_CONNECT_ERROR; break; } - remaining = max_renegotiate_ms - elapsed; + remaining = MAX_RENEG_BLOCK_TIME - elapsed; if(blocking) { - timeout = Curl_timeleft(data, NULL, FALSE); + timeout_ms = Curl_timeleft_ms(data, FALSE); - if(timeout < 0) { + if(timeout_ms < 0) { result = CURLE_OPERATION_TIMEDOUT; break; } /* the blocking is in intervals so that the progress function can be called every second */ - if(!timeout || timeout > 1000) - timeout = 1000; + if(!timeout_ms || timeout_ms > 1000) + timeout_ms = 1000; - if(timeout > remaining) - timeout = remaining; + if(timeout_ms > remaining) + timeout_ms = remaining; } else - timeout = 0; + timeout_ms = 0; SCH_DEV(infof(data, "schannel: renegotiation wait until socket is" "%s%s for up to %" FMT_TIMEDIFF_T " ms", ((readfd != CURL_SOCKET_BAD) ? " readable" : ""), ((writefd != CURL_SOCKET_BAD) ? " writeable" : ""), - timeout)); + timeout_ms)); - what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, timeout); + what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, timeout_ms); if(what > 0 && (what & (CURL_CSELECT_IN | CURL_CSELECT_OUT))) { SCH_DEV(infof(data, "schannel: renegotiation socket %s%s", @@ -1883,9 +1866,8 @@ schannel_recv_renegotiate(struct Curl_cfilter *cf, struct Curl_easy *data, return result; } -static CURLcode -schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t len, size_t *pnwritten) +static CURLcode schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data, + const void *buf, size_t len, size_t *pnwritten) { size_t data_len = 0; unsigned char *ptr = NULL; @@ -1925,7 +1907,7 @@ schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data, /* calculate the complete message length and allocate a buffer for it */ data_len = backend->stream_sizes.cbHeader + len + backend->stream_sizes.cbTrailer; - ptr = (unsigned char *)malloc(data_len); + ptr = (unsigned char *)curlx_malloc(data_len); if(!ptr) { return CURLE_OUT_OF_MEMORY; } @@ -1974,7 +1956,7 @@ schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data, while(len > *pnwritten) { size_t this_write = 0; int what; - timediff_t timeout_ms = Curl_timeleft(data, NULL, FALSE); + timediff_t timeout_ms = Curl_timeleft_ms(data, FALSE); if(timeout_ms < 0) { /* we already got the timeout */ failf(data, "schannel: timed out sending data " @@ -2000,7 +1982,8 @@ schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data, /* socket is writable */ result = Curl_conn_cf_send(cf->next, data, - ptr + *pnwritten, len - *pnwritten, + (const uint8_t *)ptr + *pnwritten, + len - *pnwritten, FALSE, &this_write); if(result == CURLE_AGAIN) continue; @@ -2014,7 +1997,7 @@ schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data, else if(sspi_status == SEC_E_INSUFFICIENT_MEMORY) { result = CURLE_OUT_OF_MEMORY; } - else{ + else { result = CURLE_SEND_ERROR; } @@ -2028,9 +2011,8 @@ schannel_send(struct Curl_cfilter *cf, struct Curl_easy *data, return result; } -static CURLcode -schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data, - char *buf, size_t len, size_t *pnread) +static CURLcode schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data, + char *buf, size_t len, size_t *pnread) { size_t size = 0; size_t nread = 0; @@ -2103,8 +2085,8 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data, if(reallocated_length < min_encdata_length) { reallocated_length = min_encdata_length; } - reallocated_buffer = realloc(backend->encdata_buffer, - reallocated_length); + reallocated_buffer = curlx_realloc(backend->encdata_buffer, + reallocated_length); if(!reallocated_buffer) { result = CURLE_OUT_OF_MEMORY; failf(data, "schannel: unable to re-allocate memory"); @@ -2166,7 +2148,7 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data, /* https://learn.microsoft.com/windows/win32/api/sspi/nf-sspi-decryptmessage */ sspi_status = Curl_pSecFn->DecryptMessage(&backend->ctxt->ctxt_handle, - &inbuf_desc, 0, NULL); + &inbuf_desc, 0, NULL); /* check if everything went fine (server may want to renegotiate or shutdown the connection context) */ @@ -2189,8 +2171,8 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data, if(reallocated_length < len) { reallocated_length = len; } - reallocated_buffer = realloc(backend->decdata_buffer, - reallocated_length); + reallocated_buffer = curlx_realloc(backend->decdata_buffer, + reallocated_length); if(!reallocated_buffer) { result = CURLE_OUT_OF_MEMORY; failf(data, "schannel: unable to re-allocate memory"); @@ -2227,7 +2209,8 @@ schannel_recv(struct Curl_cfilter *cf, struct Curl_easy *data, buffer */ memmove(backend->encdata_buffer, (backend->encdata_buffer + backend->encdata_offset) - - inbuf[3].cbBuffer, inbuf[3].cbBuffer); + inbuf[3].cbBuffer, + inbuf[3].cbBuffer); backend->encdata_offset = inbuf[3].cbBuffer; } @@ -2446,7 +2429,8 @@ static CURLcode schannel_shutdown(struct Curl_cfilter *cf, size_t written; result = Curl_conn_cf_send(cf->next, data, - outbuf.pvBuffer, outbuf.cbBuffer, + (const uint8_t *)outbuf.pvBuffer, + outbuf.cbBuffer, FALSE, &written); Curl_pSecFn->FreeContextBuffer(outbuf.pvBuffer); if(!result) { @@ -2550,7 +2534,7 @@ static void schannel_close(struct Curl_cfilter *cf, struct Curl_easy *data) static int schannel_init(void) { -#if defined(HAS_ALPN_SCHANNEL) && !defined(UNDER_CE) +#ifdef HAS_ALPN_SCHANNEL typedef const char *(APIENTRY *WINE_GET_VERSION_FN)(void); #if defined(__clang__) && __clang_major__ >= 16 #pragma clang diagnostic push @@ -2558,22 +2542,24 @@ static int schannel_init(void) #endif WINE_GET_VERSION_FN p_wine_get_version = CURLX_FUNCTION_CAST(WINE_GET_VERSION_FN, - GetProcAddress(GetModuleHandleA("ntdll"), - "wine_get_version")); + GetProcAddress(GetModuleHandle(TEXT("ntdll")), "wine_get_version")); #if defined(__clang__) && __clang_major__ >= 16 #pragma clang diagnostic pop #endif if(p_wine_get_version) { /* WINE detected */ + curl_off_t ver = 0; const char *wine_version = p_wine_get_version(); /* e.g. "6.0.2" */ /* Assume ALPN support with WINE 6.0 or upper */ - s_win_has_alpn = wine_version && atoi(wine_version) >= 6; + if(wine_version) + curlx_str_number(&wine_version, &ver, 20); + s_win_has_alpn = (ver >= 6); } else { /* ALPN is supported on Windows 8.1 / Server 2012 R2 and above. */ s_win_has_alpn = curlx_verify_windows_version(6, 3, 0, PLATFORM_WINNT, VERSION_GREATER_THAN_EQUAL); } -#endif /* HAS_ALPN_SCHANNEL && !UNDER_CE */ +#endif /* HAS_ALPN_SCHANNEL */ return Curl_sspi_global_init() == CURLE_OK ? 1 : 0; } @@ -2633,7 +2619,6 @@ static CURLcode schannel_pkp_pin_peer_pubkey(struct Curl_cfilter *cf, break; /* failed */ } - if(!(((pCertContextServer->dwCertEncodingType & X509_ASN_ENCODING) != 0) && (pCertContextServer->cbCertEncoded > 0))) break; @@ -2691,12 +2676,7 @@ static void schannel_checksum(const unsigned char *input, if(!CryptCreateHash(hProv, algId, 0, 0, &hHash)) break; /* failed */ -#ifdef __MINGW32CE__ - /* workaround for CeGCC, should be (const BYTE*) */ - if(!CryptHashData(hHash, (BYTE*)CURL_UNCONST(input), (DWORD)inputlen, 0)) -#else if(!CryptHashData(hHash, input, (DWORD)inputlen, 0)) -#endif break; /* failed */ /* get hash size */ @@ -2740,7 +2720,7 @@ static void *schannel_get_internals(struct ssl_connect_data *connssl, } HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf, - const struct Curl_easy *data) + struct Curl_easy *data) { struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); struct Curl_multi *multi = data->multi; @@ -2749,7 +2729,6 @@ HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf, 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); @@ -2760,7 +2739,7 @@ HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf, share = Curl_hash_pick(&multi->proto_hash, CURL_UNCONST(MPROTO_SCHANNEL_CERT_SHARE_KEY), - sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY)-1); + sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY) - 1); if(!share || !share->cert_store) { return NULL; } @@ -2775,8 +2754,7 @@ HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf, negative timeout means retain forever. */ timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000; if(timeout_ms >= 0) { - now = curlx_now(); - elapsed_ms = curlx_timediff(now, share->time); + elapsed_ms = curlx_ptimediff_ms(Curl_pgrs_now(data), &share->time); if(elapsed_ms >= timeout_ms) { return NULL; } @@ -2808,19 +2786,19 @@ HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf, static void schannel_cert_share_free(void *key, size_t key_len, void *p) { struct schannel_cert_share *share = p; - DEBUGASSERT(key_len == (sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY)-1)); + DEBUGASSERT(key_len == (sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY) - 1)); DEBUGASSERT(!memcmp(MPROTO_SCHANNEL_CERT_SHARE_KEY, key, key_len)); (void)key; (void)key_len; if(share->cert_store) { CertCloseStore(share->cert_store, 0); } - free(share->CAfile); - free(share); + curlx_free(share->CAfile); + curlx_free(share); } bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf, - const struct Curl_easy *data, + struct Curl_easy *data, HCERTSTORE cert_store) { struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); @@ -2838,17 +2816,17 @@ bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf, share = Curl_hash_pick(&multi->proto_hash, CURL_UNCONST(MPROTO_SCHANNEL_CERT_SHARE_KEY), - sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY)-1); + sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY) - 1); if(!share) { - share = calloc(1, sizeof(*share)); + share = curlx_calloc(1, sizeof(*share)); if(!share) { return FALSE; } if(!Curl_hash_add2(&multi->proto_hash, CURL_UNCONST(MPROTO_SCHANNEL_CERT_SHARE_KEY), - sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY)-1, + sizeof(MPROTO_SCHANNEL_CERT_SHARE_KEY) - 1, share, schannel_cert_share_free)) { - free(share); + curlx_free(share); return FALSE; } } @@ -2862,7 +2840,7 @@ bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf, } else { if(conn_config->CAfile) { - CAfile = strdup(conn_config->CAfile); + CAfile = curlx_strdup(conn_config->CAfile); if(!CAfile) { return FALSE; } @@ -2873,7 +2851,7 @@ bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf, if(share->cert_store) { CertCloseStore(share->cert_store, 0); } - free(share->CAfile); + curlx_free(share->CAfile); share->time = curlx_now(); share->cert_store = cert_store; diff --git a/lib/vtls/schannel.h b/lib/vtls/schannel.h index 9d0bea221a9b..f66bcf293338 100644 --- a/lib/vtls/schannel.h +++ b/lib/vtls/schannel.h @@ -58,7 +58,7 @@ /* has been included via the above . * Or in case of ldap.c, it was included via . * And since has this: - * #define X509_NAME ((LPCSTR) 7) + * #define X509_NAME ((LPCSTR)7) * * And in BoringSSL's there is: * typedef struct X509_name_st X509_NAME; @@ -69,15 +69,14 @@ * (and only here). */ #if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC) -# undef X509_NAME -# undef X509_CERT_PAIR -# undef X509_EXTENSIONS +#undef X509_NAME +#undef X509_CERT_PAIR +#undef X509_EXTENSIONS #endif extern const struct Curl_ssl Curl_ssl_schannel; -CURLcode Curl_verify_host(struct Curl_cfilter *cf, - struct Curl_easy *data); +CURLcode Curl_verify_host(struct Curl_cfilter *cf, struct Curl_easy *data); CURLcode Curl_verify_certificate(struct Curl_cfilter *cf, struct Curl_easy *data); diff --git a/lib/vtls/schannel_int.h b/lib/vtls/schannel_int.h index f9adb5829440..0146bf861917 100644 --- a/lib/vtls/schannel_int.h +++ b/lib/vtls/schannel_int.h @@ -29,8 +29,9 @@ #ifdef USE_SCHANNEL #include "vtls.h" +#include "../curl_sha256.h" -#if defined(_MSC_VER) && (_MSC_VER <= 1600) +#if defined(_MSC_VER) && (_MSC_VER < 1700) /* Workaround for warning: 'type cast' : conversion from 'int' to 'LPCSTR' of greater size */ #undef CERT_STORE_PROV_MEMORY @@ -157,10 +158,10 @@ struct num_ip_data { }; HCERTSTORE Curl_schannel_get_cached_cert_store(struct Curl_cfilter *cf, - const struct Curl_easy *data); + struct Curl_easy *data); bool Curl_schannel_set_cached_cert_store(struct Curl_cfilter *cf, - const struct Curl_easy *data, + struct Curl_easy *data, HCERTSTORE cert_store); #endif /* USE_SCHANNEL */ diff --git a/lib/vtls/schannel_verify.c b/lib/vtls/schannel_verify.c index d72790e9df57..e3525a110516 100644 --- a/lib/vtls/schannel_verify.c +++ b/lib/vtls/schannel_verify.c @@ -33,47 +33,28 @@ #ifdef USE_SCHANNEL #ifndef USE_WINDOWS_SSPI -# error "cannot compile SCHANNEL support without SSPI." +#error "cannot compile SCHANNEL support without SSPI." #endif #include "schannel.h" #include "schannel_int.h" +#include "../curlx/fopen.h" #include "../curlx/inet_pton.h" #include "vtls.h" #include "vtls_int.h" -#include "../sendf.h" +#include "../curl_trc.h" #include "../strerror.h" #include "../curlx/winapi.h" #include "../curlx/multibyte.h" #include "hostcheck.h" #include "../curlx/version_win32.h" -/* The last #include file should be: */ -#include "../curl_memory.h" -#include "../memdebug.h" - #define BACKEND ((struct schannel_ssl_backend_data *)connssl->backend) -#ifdef __MINGW32CE__ -#define CERT_QUERY_OBJECT_BLOB 0x00000002 -#define CERT_QUERY_CONTENT_CERT 1 -#define CERT_QUERY_CONTENT_FLAG_CERT (1 << CERT_QUERY_CONTENT_CERT) -#define CERT_QUERY_FORMAT_BINARY 1 -#define CERT_QUERY_FORMAT_BASE64_ENCODED 2 -#define CERT_QUERY_FORMAT_ASN_ASCII_HEX_ENCODED 3 -#define CERT_QUERY_FORMAT_FLAG_ALL \ - (1 << CERT_QUERY_FORMAT_BINARY) | \ - (1 << CERT_QUERY_FORMAT_BASE64_ENCODED) | \ - (1 << CERT_QUERY_FORMAT_ASN_ASCII_HEX_ENCODED) -#define CERT_CHAIN_REVOCATION_CHECK_CHAIN 0x20000000 -#define CERT_NAME_DISABLE_IE4_UTF8_FLAG 0x00010000 -#define CERT_TRUST_IS_OFFLINE_REVOCATION 0x01000000 -#endif /* __MINGW32CE__ */ - #define MAX_CAFILE_SIZE 1048576 /* 1 MiB */ -#define BEGIN_CERT "-----BEGIN CERTIFICATE-----" -#define END_CERT "\n-----END CERTIFICATE-----" +#define BEGIN_CERT "-----BEGIN CERTIFICATE-----" +#define END_CERT "\n-----END CERTIFICATE-----" struct cert_chain_engine_config_win8 { DWORD cbSize; @@ -112,7 +93,6 @@ struct cert_chain_engine_config_win7 { HCERTSTORE hExclusiveTrustedPeople; }; -#ifndef UNDER_CE static int is_cr_or_lf(char c) { return c == '\r' || c == '\n'; @@ -178,11 +158,12 @@ static CURLcode add_certs_data_to_store(HCERTSTORE trust_store, const CERT_CONTEXT *cert_context = NULL; BOOL add_cert_result = FALSE; DWORD actual_content_type = 0; - DWORD cert_size = (DWORD) - ((end_cert_ptr + end_cert_len) - begin_cert_ptr); + DWORD cert_size = + (DWORD)((end_cert_ptr + end_cert_len) - begin_cert_ptr); cert_blob.pbData = (BYTE *)CURL_UNCONST(begin_cert_ptr); cert_blob.cbData = cert_size; + /* Caution: CryptQueryObject() is deprecated */ if(!CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &cert_blob, CERT_QUERY_CONTENT_FLAG_CERT, @@ -221,7 +202,6 @@ static CURLcode add_certs_data_to_store(HCERTSTORE trust_store, cert_context, CERT_STORE_ADD_ALWAYS, NULL); - CertFreeCertificateContext(cert_context); if(!add_cert_result) { char buffer[WINAPI_ERROR_LEN]; failf(data, @@ -237,6 +217,21 @@ static CURLcode add_certs_data_to_store(HCERTSTORE trust_store, num_certs++; } } + + switch(actual_content_type) { + case CERT_QUERY_CONTENT_CERT: + case CERT_QUERY_CONTENT_SERIALIZED_CERT: + CertFreeCertificateContext(cert_context); + break; + case CERT_QUERY_CONTENT_CRL: + case CERT_QUERY_CONTENT_SERIALIZED_CRL: + CertFreeCRLContext((PCCRL_CONTEXT)cert_context); + break; + case CERT_QUERY_CONTENT_CTL: + case CERT_QUERY_CONTENT_SERIALIZED_CTL: + CertFreeCTLContext((PCCTL_CONTEXT)cert_context); + break; + } } } } @@ -244,13 +239,11 @@ static CURLcode add_certs_data_to_store(HCERTSTORE trust_store, if(result == CURLE_OK) { if(!num_certs) { - infof(data, - "schannel: did not add any certificates from CA file '%s'", + infof(data, "schannel: did not add any certificates from CA file '%s'", ca_file_text); } else { - infof(data, - "schannel: added %d certificate(s) from CA file '%s'", + infof(data, "schannel: added %d certificate(s) from CA file '%s'", num_certs, ca_file_text); } } @@ -262,41 +255,27 @@ static CURLcode add_certs_file_to_store(HCERTSTORE trust_store, struct Curl_easy *data) { CURLcode result; - HANDLE ca_file_handle = INVALID_HANDLE_VALUE; + HANDLE ca_file_handle; LARGE_INTEGER file_size; char *ca_file_buffer = NULL; - TCHAR *ca_file_tstr = NULL; size_t ca_file_bufsize = 0; DWORD total_bytes_read = 0; - ca_file_tstr = curlx_convert_UTF8_to_tchar(ca_file); - if(!ca_file_tstr) { - char buffer[WINAPI_ERROR_LEN]; - failf(data, - "schannel: invalid path name for CA file '%s': %s", - ca_file, - curlx_winapi_strerror(GetLastError(), buffer, sizeof(buffer))); - result = CURLE_SSL_CACERT_BADFILE; - goto cleanup; - } - /* * Read the CA file completely into memory before parsing it. This * optimizes for the common case where the CA file will be relatively * small ( < 1 MiB ). */ - ca_file_handle = CreateFile(ca_file_tstr, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); + ca_file_handle = curlx_CreateFile(ca_file, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); if(ca_file_handle == INVALID_HANDLE_VALUE) { char buffer[WINAPI_ERROR_LEN]; - failf(data, - "schannel: failed to open CA file '%s': %s", - ca_file, + failf(data, "schannel: failed to open CA file '%s': %s", ca_file, curlx_winapi_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; goto cleanup; @@ -304,8 +283,7 @@ static CURLcode add_certs_file_to_store(HCERTSTORE trust_store, if(!GetFileSizeEx(ca_file_handle, &file_size)) { char buffer[WINAPI_ERROR_LEN]; - failf(data, - "schannel: failed to determine size of CA file '%s': %s", + failf(data, "schannel: failed to determine size of CA file '%s': %s", ca_file, curlx_winapi_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; @@ -313,15 +291,14 @@ static CURLcode add_certs_file_to_store(HCERTSTORE trust_store, } if(file_size.QuadPart > MAX_CAFILE_SIZE) { - failf(data, - "schannel: CA file exceeds max size of %u bytes", + failf(data, "schannel: CA file exceeds max size of %u bytes", MAX_CAFILE_SIZE); result = CURLE_SSL_CACERT_BADFILE; goto cleanup; } ca_file_bufsize = (size_t)file_size.QuadPart; - ca_file_buffer = (char *)malloc(ca_file_bufsize + 1); + ca_file_buffer = (char *)curlx_malloc(ca_file_bufsize + 1); if(!ca_file_buffer) { result = CURLE_OUT_OF_MEMORY; goto cleanup; @@ -334,9 +311,7 @@ static CURLcode add_certs_file_to_store(HCERTSTORE trust_store, if(!ReadFile(ca_file_handle, ca_file_buffer + total_bytes_read, bytes_to_read, &bytes_read, NULL)) { char buffer[WINAPI_ERROR_LEN]; - failf(data, - "schannel: failed to read from CA file '%s': %s", - ca_file, + failf(data, "schannel: failed to read from CA file '%s': %s", ca_file, curlx_winapi_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; goto cleanup; @@ -363,7 +338,6 @@ static CURLcode add_certs_file_to_store(HCERTSTORE trust_store, CloseHandle(ca_file_handle); } Curl_safefree(ca_file_buffer); - curlx_unicodefree(ca_file_tstr); return result; } @@ -387,10 +361,12 @@ static DWORD cert_get_name_string(struct Curl_easy *data, LPTSTR current_pos = NULL; DWORD i; -/* Offered by mingw-w64 v4+. MS SDK ~10+/~VS2017+. */ -#ifdef CERT_NAME_SEARCH_ALL_NAMES_FLAG /* CERT_NAME_SEARCH_ALL_NAMES_FLAG is available from Windows 8 onwards. */ if(Win8_compat) { +/* Offered by mingw-w64 v4+. MS SDK ~10+/~VS2017+. */ +#ifndef CERT_NAME_SEARCH_ALL_NAMES_FLAG +#define CERT_NAME_SEARCH_ALL_NAMES_FLAG 0x2 +#endif /* CertGetNameString will provide the 8-bit character string without * any decoding */ DWORD name_flags = @@ -403,10 +379,6 @@ static DWORD cert_get_name_string(struct Curl_easy *data, length); return actual_length; } -#else - (void)cert_context; - (void)Win8_compat; -#endif if(!alt_name_info) return 0; @@ -461,12 +433,11 @@ static DWORD cert_get_name_string(struct Curl_easy *data, } /* -* Returns TRUE if the hostname is a numeric IPv4/IPv6 Address, -* and populates the buffer with IPv4/IPv6 info. -*/ + * Returns TRUE if the hostname is a numeric IPv4/IPv6 Address, + * and populates the buffer with IPv4/IPv6 info. + */ -static bool get_num_host_info(struct num_ip_data *ip_blob, - LPCSTR hostname) +static bool get_num_host_info(struct num_ip_data *ip_blob, LPCSTR hostname) { struct in_addr ia; struct in6_addr ia6; @@ -526,75 +497,20 @@ static bool get_alt_name_info(struct Curl_easy *data, &decode_para, alt_name_info, alt_name_info_size)) { - failf(data, - "schannel: CryptDecodeObjectEx() returned no alternate name " - "information."); + failf(data, "schannel: CryptDecodeObjectEx() returned no alternate name " + "information."); return result; } result = TRUE; return result; } -#endif /* !UNDER_CE */ /* Verify the server's hostname */ -CURLcode Curl_verify_host(struct Curl_cfilter *cf, - struct Curl_easy *data) +CURLcode Curl_verify_host(struct Curl_cfilter *cf, struct Curl_easy *data) { CURLcode result = CURLE_PEER_FAILED_VERIFICATION; struct ssl_connect_data *connssl = cf->ctx; CERT_CONTEXT *pCertContextServer = NULL; -#ifdef UNDER_CE - TCHAR cert_hostname_buff[256]; - DWORD len; - - /* This code does not support certificates with multiple alternative names. - * Right now we are only asking for the first preferred alternative name. - * Instead we would need to do all via CERT_NAME_SEARCH_ALL_NAMES_FLAG - * (If Windows CE supports that?) and run this section in a loop for each. - * https://learn.microsoft.com/windows/win32/api/wincrypt/nf-wincrypt-certgetnamestringa - * curl: (51) schannel: CertGetNameString() certificate hostname - * (.google.com) did not match connection (google.com) - */ - len = CertGetNameString(pCertContextServer, - CERT_NAME_DNS_TYPE, - CERT_NAME_DISABLE_IE4_UTF8_FLAG, - NULL, - cert_hostname_buff, - 256); - if(len > 0) { - /* Comparing the cert name and the connection hostname encoded as UTF-8 - * is acceptable since both values are assumed to use ASCII - * (or some equivalent) encoding - */ - char *cert_hostname = curlx_convert_tchar_to_UTF8(cert_hostname_buff); - if(!cert_hostname) { - result = CURLE_OUT_OF_MEMORY; - } - else{ - const char *conn_hostname = connssl->peer.hostname; - if(Curl_cert_hostcheck(cert_hostname, strlen(cert_hostname), - conn_hostname, strlen(conn_hostname))) { - infof(data, - "schannel: connection hostname (%s) validated " - "against certificate name (%s)\n", - conn_hostname, cert_hostname); - result = CURLE_OK; - } - else{ - failf(data, - "schannel: connection hostname (%s) " - "does not match certificate name (%s)", - conn_hostname, cert_hostname); - } - Curl_safefree(cert_hostname); - } - } - else { - failf(data, - "schannel: CertGetNameString did not provide any " - "certificate name information"); - } -#else SECURITY_STATUS sspi_status; TCHAR *cert_hostname_buff = NULL; size_t cert_hostname_buff_index = 0; @@ -661,7 +577,7 @@ CURLcode Curl_verify_host(struct Curl_cfilter *cf, /* CertGetNameString guarantees that the returned name will not contain * embedded null bytes. This appears to be undocumented behavior. */ - cert_hostname_buff = (LPTSTR)malloc(len * sizeof(TCHAR)); + cert_hostname_buff = (LPTSTR)curlx_malloc(len * sizeof(TCHAR)); if(!cert_hostname_buff) { result = CURLE_OUT_OF_MEMORY; goto cleanup; @@ -720,7 +636,7 @@ CURLcode Curl_verify_host(struct Curl_cfilter *cf, result = CURLE_PEER_FAILED_VERIFICATION; } - curlx_unicodefree(cert_hostname); + curlx_free(cert_hostname); } } @@ -740,7 +656,6 @@ CURLcode Curl_verify_host(struct Curl_cfilter *cf, if(pCertContextServer) CertFreeCertificateContext(pCertContextServer); -#endif /* !UNDER_CE */ return result; } @@ -757,10 +672,8 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf, CERT_CONTEXT *pCertContextServer = NULL; const CERT_CHAIN_CONTEXT *pChainContext = NULL; HCERTCHAINENGINE cert_chain_engine = NULL; -#ifndef UNDER_CE HCERTSTORE trust_store = NULL; HCERTSTORE own_trust_store = NULL; -#endif /* !UNDER_CE */ DEBUGASSERT(BACKEND); @@ -776,7 +689,6 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf, result = CURLE_PEER_FAILED_VERIFICATION; } -#ifndef UNDER_CE if(result == CURLE_OK && (conn_config->CAfile || conn_config->ca_info_blob) && BACKEND->use_manual_cred_validation) { @@ -870,7 +782,6 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf, } } } -#endif /* !UNDER_CE */ if(result == CURLE_OK) { CERT_CHAIN_PARA ChainPara; @@ -904,7 +815,7 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf, * list URL, or when the list could not be downloaded because the * server is currently unreachable. */ dwTrustErrorMask &= ~(DWORD)(CERT_TRUST_REVOCATION_STATUS_UNKNOWN | - CERT_TRUST_IS_OFFLINE_REVOCATION); + CERT_TRUST_IS_OFFLINE_REVOCATION); } if(dwTrustErrorMask) { @@ -934,7 +845,6 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf, } } -#ifndef UNDER_CE if(cert_chain_engine) { CertFreeCertificateChainEngine(cert_chain_engine); } @@ -942,7 +852,6 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf, if(own_trust_store) { CertCloseStore(own_trust_store, 0); } -#endif /* !UNDER_CE */ if(pChainContext) CertFreeCertificateChain(pChainContext); diff --git a/lib/vtls/vtls.c b/lib/vtls/vtls.c index 7ee9699dbf0b..78f17ea1328e 100644 --- a/lib/vtls/vtls.c +++ b/lib/vtls/vtls.c @@ -59,38 +59,30 @@ #include "rustls.h" /* Rustls versions */ #include "../slist.h" -#include "../sendf.h" +#include "../curl_trc.h" #include "../strcase.h" #include "../url.h" #include "../progress.h" -#include "../share.h" -#include "../multiif.h" #include "../curlx/fopen.h" #include "../curlx/timeval.h" -#include "../curl_md5.h" #include "../curl_sha256.h" -#include "../curlx/warnless.h" #include "../curlx/base64.h" #include "../curlx/inet_pton.h" #include "../connect.h" #include "../select.h" #include "../setopt.h" #include "../strdup.h" -#include "../rand.h" +#include "../curlx/strcopy.h" #ifdef USE_APPLE_SECTRUST #include #endif -/* The last #include files should be: */ -#include "../curl_memory.h" -#include "../memdebug.h" - #define CLONE_STRING(var) \ do { \ if(source->var) { \ - dest->var = strdup(source->var); \ + dest->var = curlx_strdup(source->var); \ if(!dest->var) \ return FALSE; \ } \ @@ -98,21 +90,20 @@ dest->var = NULL; \ } while(0) -#define CLONE_BLOB(var) \ - do { \ - if(blobdup(&dest->var, source->var)) \ - return FALSE; \ +#define CLONE_BLOB(var) \ + do { \ + if(blobdup(&dest->var, source->var)) \ + return FALSE; \ } while(0) -static CURLcode blobdup(struct curl_blob **dest, - struct curl_blob *src) +static CURLcode blobdup(struct curl_blob **dest, struct curl_blob *src) { DEBUGASSERT(dest); DEBUGASSERT(!*dest); if(src) { /* only if there is data to dupe! */ struct curl_blob *d; - d = malloc(sizeof(struct curl_blob) + src->len); + d = curlx_malloc(sizeof(struct curl_blob) + src->len); if(!d) return CURLE_OUT_OF_MEMORY; d->len = src->len; @@ -151,22 +142,28 @@ static const struct alpn_spec ALPN_SPEC_H2 = { static const struct alpn_spec ALPN_SPEC_H2_H11 = { { ALPN_H2, ALPN_HTTP_1_1 }, 2 }; +static const struct alpn_spec ALPN_SPEC_H11_H2 = { + { ALPN_HTTP_1_1, ALPN_H2 }, 2 +}; #endif #if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_PROXY) -static const struct alpn_spec * -alpn_get_spec(http_majors allowed, bool use_alpn) +static const struct alpn_spec *alpn_get_spec(http_majors wanted, + http_majors preferred, + bool use_alpn) { if(!use_alpn) return NULL; #ifdef USE_HTTP2 - if(allowed & CURL_HTTP_V2x) { - if(allowed & CURL_HTTP_V1x) - return &ALPN_SPEC_H2_H11; + if(wanted & CURL_HTTP_V2x) { + if(wanted & CURL_HTTP_V1x) + return (preferred == CURL_HTTP_V1x) ? + &ALPN_SPEC_H11_H2 : &ALPN_SPEC_H2_H11; return &ALPN_SPEC_H2; } #else - (void)allowed; + (void)wanted; + (void)preferred; #endif /* Use the ALPN protocol "http/1.1" for HTTP/1.x. Avoid "http/1.0" because some servers do not support it. */ @@ -175,7 +172,6 @@ alpn_get_spec(http_majors allowed, bool use_alpn) #endif /* !CURL_DISABLE_HTTP || !CURL_DISABLE_PROXY */ #endif /* USE_SSL */ - void Curl_ssl_easy_config_init(struct Curl_easy *data) { /* @@ -190,10 +186,9 @@ void Curl_ssl_easy_config_init(struct Curl_easy *data) #endif } -static bool -match_ssl_primary_config(struct Curl_easy *data, - struct ssl_primary_config *c1, - struct ssl_primary_config *c2) +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) && @@ -311,7 +306,6 @@ CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data) if(result) return result; } - sslc->primary.CApath = data->set.str[STRING_SSL_CAPATH]; #endif #ifdef CURL_CA_BUNDLE if(!sslc->custom_cafile && !set->str[STRING_SSL_CAFILE]) { @@ -323,14 +317,14 @@ CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data) } sslc->primary.CAfile = data->set.str[STRING_SSL_CAFILE]; sslc->primary.CRLfile = data->set.str[STRING_SSL_CRLFILE]; + sslc->primary.CApath = data->set.str[STRING_SSL_CAPATH]; sslc->primary.issuercert = data->set.str[STRING_SSL_ISSUERCERT]; sslc->primary.issuercert_blob = data->set.blobs[BLOB_SSL_ISSUERCERT]; sslc->primary.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST]; sslc->primary.cipher_list13 = data->set.str[STRING_SSL_CIPHER13_LIST]; sslc->primary.signature_algorithms = data->set.str[STRING_SSL_SIGNATURE_ALGORITHMS]; - sslc->primary.pinned_key = - data->set.str[STRING_SSL_PINNEDPUBLICKEY]; + sslc->primary.pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY]; sslc->primary.cert_blob = data->set.blobs[BLOB_CERT]; sslc->primary.ca_info_blob = data->set.blobs[BLOB_CAINFO]; sslc->primary.curves = data->set.str[STRING_SSL_EC_CURVES]; @@ -359,7 +353,6 @@ CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data) if(result) return result; } - sslc->primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY]; #endif #ifdef CURL_CA_BUNDLE if(!sslc->custom_cafile && !set->str[STRING_SSL_CAFILE_PROXY]) { @@ -371,6 +364,7 @@ CURLcode Curl_ssl_easy_config_complete(struct Curl_easy *data) #endif } sslc->primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY]; + sslc->primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY]; sslc->primary.cipher_list = data->set.str[STRING_SSL_CIPHER_LIST_PROXY]; sslc->primary.cipher_list13 = data->set.str[STRING_SSL_CIPHER13_LIST_PROXY]; sslc->primary.pinned_key = data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]; @@ -504,16 +498,16 @@ static struct ssl_connect_data *cf_ctx_new(struct Curl_easy *data, struct ssl_connect_data *ctx; (void)data; - ctx = calloc(1, sizeof(*ctx)); + ctx = curlx_calloc(1, sizeof(*ctx)); if(!ctx) return NULL; ctx->ssl_impl = Curl_ssl; ctx->alpn = alpn; Curl_bufq_init2(&ctx->earlydata, CURL_SSL_EARLY_MAX, 1, BUFQ_OPT_NO_SPARES); - ctx->backend = calloc(1, ctx->ssl_impl->sizeof_ssl_backend_data); + ctx->backend = curlx_calloc(1, ctx->ssl_impl->sizeof_ssl_backend_data); if(!ctx->backend) { - free(ctx); + curlx_free(ctx); return NULL; } return ctx; @@ -524,8 +518,8 @@ static void cf_ctx_free(struct ssl_connect_data *ctx) if(ctx) { Curl_safefree(ctx->negotiated.alpn); Curl_bufq_free(&ctx->earlydata); - free(ctx->backend); - free(ctx); + curlx_free(ctx->backend); + curlx_free(ctx); } } @@ -543,9 +537,9 @@ void Curl_ssl_close_all(struct Curl_easy *data) Curl_ssl->close_all(data); } -CURLcode Curl_ssl_adjust_pollset(struct Curl_cfilter *cf, - struct Curl_easy *data, - struct easy_pollset *ps) +CURLcode Curl_ssl_adjust_pollset(struct Curl_cfilter *cf, + struct Curl_easy *data, + struct easy_pollset *ps) { struct ssl_connect_data *connssl = cf->ctx; @@ -618,7 +612,7 @@ void Curl_ssl_free_certinfo(struct Curl_easy *data) ci->certinfo[i] = NULL; } - free(ci->certinfo); /* free the actual array too */ + curlx_free(ci->certinfo); /* free the actual array too */ ci->certinfo = NULL; ci->num_of_certs = 0; } @@ -633,7 +627,7 @@ CURLcode Curl_ssl_init_certinfo(struct Curl_easy *data, int num) Curl_ssl_free_certinfo(data); /* Allocate the required certificate information structures */ - table = calloc((size_t) num, sizeof(struct curl_slist *)); + table = curlx_calloc((size_t)num, sizeof(struct curl_slist *)); if(!table) return CURLE_OUT_OF_MEMORY; @@ -666,8 +660,7 @@ CURLcode Curl_ssl_push_certinfo_len(struct Curl_easy *data, curlx_dyn_addn(&build, value, valuelen)) return CURLE_OUT_OF_MEMORY; - nl = Curl_slist_append_nodup(ci->certinfo[certnum], - curlx_dyn_ptr(&build)); + nl = Curl_slist_append_nodup(ci->certinfo[certnum], curlx_dyn_ptr(&build)); if(!nl) { curlx_dyn_free(&build); curl_slist_free_all(ci->certinfo[certnum]); @@ -773,8 +766,9 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data, /* only do this if pinnedpubkey starts with "sha256//", length 8 */ if(!strncmp(pinnedpubkey, "sha256//", 8)) { CURLcode encode; - size_t encodedlen = 0; - char *encoded = NULL, *pinkeycopy, *begin_pos, *end_pos; + char *cert_hash = NULL; + const char *pinned_hash, *end_pos; + size_t cert_hash_len = 0, pinned_hash_len; unsigned char *sha256sumdigest; if(!Curl_ssl->sha256sum) { @@ -783,58 +777,45 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data, } /* compute sha256sum of public key */ - sha256sumdigest = malloc(CURL_SHA256_DIGEST_LENGTH); + sha256sumdigest = curlx_malloc(CURL_SHA256_DIGEST_LENGTH); if(!sha256sumdigest) return CURLE_OUT_OF_MEMORY; encode = Curl_ssl->sha256sum(pubkey, pubkeylen, sha256sumdigest, CURL_SHA256_DIGEST_LENGTH); if(!encode) - encode = curlx_base64_encode((char *)sha256sumdigest, - CURL_SHA256_DIGEST_LENGTH, &encoded, - &encodedlen); + encode = curlx_base64_encode(sha256sumdigest, + CURL_SHA256_DIGEST_LENGTH, + &cert_hash, &cert_hash_len); Curl_safefree(sha256sumdigest); if(encode) return encode; - infof(data, " public key hash: sha256//%s", encoded); + infof(data, " public key hash: sha256//%s", cert_hash); - /* it starts with sha256//, copy so we can modify it */ - pinkeycopy = strdup(pinnedpubkey); - if(!pinkeycopy) { - Curl_safefree(encoded); - return CURLE_OUT_OF_MEMORY; - } - /* point begin_pos to the copy, and start extracting keys */ - begin_pos = pinkeycopy; - do { - end_pos = strstr(begin_pos, ";sha256//"); - /* - * if there is an end_pos, null-terminate, otherwise it will go to the - * end of the original string - */ - if(end_pos) - end_pos[0] = '\0'; - - /* compare base64 sha256 digests, 8 is the length of "sha256//" */ - if(encodedlen == strlen(begin_pos + 8) && - !memcmp(encoded, begin_pos + 8, encodedlen)) { + pinned_hash = pinnedpubkey; + while(pinned_hash && + !strncmp(pinned_hash, "sha256//", (sizeof("sha256//") - 1))) { + pinned_hash = pinned_hash + (sizeof("sha256//") - 1); + end_pos = strchr(pinned_hash, ';'); + pinned_hash_len = end_pos ? + (size_t)(end_pos - pinned_hash) : strlen(pinned_hash); + + /* compare base64 sha256 digests" */ + if(cert_hash_len == pinned_hash_len && + !memcmp(cert_hash, pinned_hash, cert_hash_len)) { + DEBUGF(infof(data, "public key hash matches pinned value")); result = CURLE_OK; break; } - /* - * change back the null-terminator we changed earlier, - * and look for next begin - */ - if(end_pos) { - end_pos[0] = ';'; - begin_pos = strstr(end_pos, "sha256//"); - } - } while(end_pos && begin_pos); - Curl_safefree(encoded); - Curl_safefree(pinkeycopy); + DEBUGF(infof(data, "public key hash does not match 'sha256//%.*s'", + (int)pinned_hash_len, pinned_hash)); + /* next one or we are at the end */ + pinned_hash = end_pos ? (end_pos + 1) : NULL; + } + Curl_safefree(cert_hash); } else { long filesize; @@ -862,7 +843,7 @@ CURLcode Curl_pin_peer_pubkey(struct Curl_easy *data, * if the size of our certificate is bigger than the file * size then it cannot match */ - size = curlx_sotouz((curl_off_t) filesize); + size = curlx_sotouz((curl_off_t)filesize); if(pubkeylen > size) goto end; @@ -1102,10 +1083,7 @@ static size_t multissl_version(char *buffer, size_t size) } if(size) { - if(backends_len < size) - strcpy(buffer, backends); - else - *buffer = 0; /* did not fit */ + curlx_strcopy(buffer, size, backends, backends_len); } return 0; } @@ -1131,7 +1109,7 @@ static int multissl_setup(const struct Curl_ssl *backend) for(i = 0; available_backends[i]; i++) { if(curl_strequal(env, available_backends[i]->info.name)) { Curl_ssl = available_backends[i]; - free(env); + curlx_free(env); return 0; } } @@ -1142,7 +1120,7 @@ static int multissl_setup(const struct Curl_ssl *backend) if(curl_strequal(CURL_DEFAULT_SSL_BACKEND, available_backends[i]->info.name)) { Curl_ssl = available_backends[i]; - free(env); + curlx_free(env); return 0; } } @@ -1150,7 +1128,7 @@ static int multissl_setup(const struct Curl_ssl *backend) /* Fall back to first available backend */ Curl_ssl = available_backends[0]; - free(env); + curlx_free(env); return 0; } @@ -1203,7 +1181,7 @@ void Curl_ssl_peer_cleanup(struct ssl_peer *peer) { Curl_safefree(peer->sni); if(peer->dispname != peer->hostname) - free(peer->dispname); + curlx_free(peer->dispname); peer->dispname = NULL; Curl_safefree(peer->hostname); Curl_safefree(peer->scache_key); @@ -1279,13 +1257,13 @@ CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, goto out; } - peer->hostname = strdup(ehostname); + peer->hostname = curlx_strdup(ehostname); if(!peer->hostname) goto out; if(!edispname || !strcmp(ehostname, edispname)) peer->dispname = peer->hostname; else { - peer->dispname = strdup(edispname); + peer->dispname = curlx_strdup(edispname); if(!peer->dispname) goto out; } @@ -1294,10 +1272,10 @@ CURLcode Curl_ssl_peer_init(struct ssl_peer *peer, /* 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] == '.')) + if(len && (peer->hostname[len - 1] == '.')) len--; if(len < USHRT_MAX) { - peer->sni = calloc(1, len + 1); + peer->sni = curlx_calloc(1, len + 1); if(!peer->sni) goto out; Curl_strntolower(peer->sni, peer->hostname, len); @@ -1365,6 +1343,15 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf, DEBUGASSERT(connssl); *done = FALSE; + + if(!connssl->prefs_checked) { + if(!ssl_prefs_check(data)) { + result = CURLE_SSL_CONNECT_ERROR; + goto out; + } + connssl->prefs_checked = TRUE; + } + if(!connssl->peer.hostname) { char tls_id[80]; connssl->ssl_impl->version(tls_id, sizeof(tls_id) - 1); @@ -1373,18 +1360,13 @@ static CURLcode ssl_cf_connect(struct Curl_cfilter *cf, goto out; } - if(!connssl->prefs_checked) { - if(!ssl_prefs_check(data)) - return CURLE_SSL_CONNECT_ERROR; - connssl->prefs_checked = TRUE; - } - result = connssl->ssl_impl->do_connect(cf, data, done); if(!result && *done) { cf->connected = TRUE; - if(connssl->state == ssl_connection_complete) - connssl->handshake_done = curlx_now(); + if(connssl->state == ssl_connection_complete) { + connssl->handshake_done = *Curl_pgrs_now(data); + } /* Connection can be deferred when sending early data */ DEBUGASSERT(connssl->state == ssl_connection_complete || connssl->state == ssl_connection_deferred); @@ -1433,7 +1415,7 @@ static CURLcode ssl_cf_connect_deferred(struct Curl_cfilter *cf, result = ssl_cf_set_earlydata(cf, data, buf, blen); if(result) return result; - /* we buffered any early data we'd like to send. Actually + /* we buffered any early data we would like to send. Actually * do the connect now which sends it and performs the handshake. */ connssl->earlydata_state = ssl_earlydata_sending; connssl->earlydata_skip = Curl_bufq_len(&connssl->earlydata); @@ -1487,7 +1469,7 @@ static bool ssl_cf_data_pending(struct Curl_cfilter *cf, static CURLcode ssl_cf_send(struct Curl_cfilter *cf, struct Curl_easy *data, - const void *buf, size_t blen, + const uint8_t *buf, size_t blen, bool eos, size_t *pnwritten) { struct ssl_connect_data *connssl = cf->ctx; @@ -1519,7 +1501,7 @@ static CURLcode ssl_cf_send(struct Curl_cfilter *cf, } else { *pnwritten = connssl->earlydata_skip; - buf = ((const char *)buf) + connssl->earlydata_skip; + buf = buf + connssl->earlydata_skip; blen -= connssl->earlydata_skip; connssl->earlydata_skip = 0; } @@ -1577,7 +1559,7 @@ static CURLcode ssl_cf_shutdown(struct Curl_cfilter *cf, *done = TRUE; /* If we have done the SSL handshake, shut down the connection cleanly */ if(cf->connected && (connssl->state == ssl_connection_complete) && - !cf->shutdown && Curl_ssl->shut_down) { + !cf->shutdown && Curl_ssl->shut_down) { struct cf_call_data save; CF_DATA_SAVE(save, cf, data); @@ -1737,6 +1719,7 @@ static CURLcode cf_ssl_create(struct Curl_cfilter **pcf, ctx = cf_ctx_new(data, NULL); #else ctx = cf_ctx_new(data, alpn_get_spec(data->state.http_neg.wanted, + data->state.http_neg.preferred, conn->bits.tls_enable_alpn)); #endif if(!ctx) { @@ -1789,17 +1772,17 @@ static CURLcode cf_ssl_proxy_create(struct Curl_cfilter **pcf, CURLcode result; /* ALPN is default, but if user explicitly disables it, obey */ bool use_alpn = data->set.ssl_enable_alpn; - http_majors allowed = CURL_HTTP_V1x; + http_majors wanted = CURL_HTTP_V1x; (void)conn; #ifdef USE_HTTP2 if(conn->http_proxy.proxytype == CURLPROXY_HTTPS2) { use_alpn = TRUE; - allowed = (CURL_HTTP_V1x|CURL_HTTP_V2x); + wanted = (CURL_HTTP_V1x | CURL_HTTP_V2x); } #endif - ctx = cf_ctx_new(data, alpn_get_spec(allowed, use_alpn)); + ctx = cf_ctx_new(data, alpn_get_spec(wanted, 0, use_alpn)); if(!ctx) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -1851,16 +1834,17 @@ static CURLcode vtls_shutdown_blocking(struct Curl_cfilter *cf, *done = FALSE; while(!result && !*done && loop--) { - timeout_ms = Curl_shutdown_timeleft(cf->conn, cf->sockindex, NULL); + timeout_ms = Curl_shutdown_timeleft(data, cf->conn, cf->sockindex); if(timeout_ms < 0) { /* no need to continue if time is already up */ failf(data, "SSL shutdown timeout"); - return CURLE_OPERATION_TIMEDOUT; + result = CURLE_OPERATION_TIMEDOUT; + goto out; } result = connssl->ssl_impl->shut_down(cf, data, send_shutdown, done); - if(result ||*done) + if(result || *done) goto out; if(connssl->io_need) { @@ -1897,7 +1881,7 @@ CURLcode Curl_ssl_cfilter_remove(struct Curl_easy *data, if(cf->cft == &Curl_cft_ssl) { bool done; CURL_TRC_CF(data, cf, "shutdown and remove SSL, start"); - Curl_shutdown_start(data, sockindex, 0, NULL); + Curl_shutdown_start(data, sockindex, 0); result = vtls_shutdown_blocking(cf, data, send_shutdown, &done); Curl_shutdown_clear(data, sockindex); if(!result && !done) /* blocking failed? */ @@ -1949,7 +1933,7 @@ CURLcode Curl_alpn_to_proto_buf(struct alpn_proto_buf *buf, len = strlen(spec->entries[i]); if(len >= ALPN_NAME_MAX) return CURLE_FAILED_INIT; - blen = (unsigned char)len; + blen = (unsigned char)len; if(off + blen + 1 >= (int)sizeof(buf->data)) return CURLE_FAILED_INIT; buf->data[off++] = blen; @@ -2055,15 +2039,13 @@ CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf, if(proto && proto_len) { if(memchr(proto, '\0', proto_len)) { failf(data, "ALPN: server selected protocol contains NUL. " - "Refusing to continue."); + "Refusing to continue."); result = CURLE_SSL_CONNECT_ERROR; goto out; } - connssl->negotiated.alpn = malloc(proto_len + 1); + connssl->negotiated.alpn = Curl_memdup0((const char *)proto, proto_len); if(!connssl->negotiated.alpn) return CURLE_OUT_OF_MEMORY; - memcpy(connssl->negotiated.alpn, proto, proto_len); - connssl->negotiated.alpn[proto_len] = 0; } if(proto && proto_len) { diff --git a/lib/vtls/vtls.h b/lib/vtls/vtls.h index c62b8ae25842..b5b517f0b6fa 100644 --- a/lib/vtls/vtls.h +++ b/lib/vtls/vtls.h @@ -99,10 +99,6 @@ CURLsslset Curl_init_sslset_nolock(curl_sslbackend id, const char *name, #define MAX_PINNED_PUBKEY_SIZE 1048576 /* 1MB */ #endif -#ifndef CURL_SHA256_DIGEST_LENGTH -#define CURL_SHA256_DIGEST_LENGTH 32 /* fixed size */ -#endif - curl_sslbackend Curl_ssl_backend(void); /** @@ -169,6 +165,7 @@ void Curl_ssl_version(char *buffer, size_t size); /* Certificate information list handling. */ #define CURL_X509_STR_MAX 100000 +#define MAX_ALLOWED_CERT_AMOUNT 100 void Curl_ssl_free_certinfo(struct Curl_easy *data); CURLcode Curl_ssl_init_certinfo(struct Curl_easy *data, int num); @@ -256,16 +253,16 @@ extern struct Curl_cftype Curl_cft_ssl_proxy; #define Curl_ssl_init() 1 #define Curl_ssl_cleanup() Curl_nop_stmt #define Curl_ssl_close_all(x) Curl_nop_stmt -#define Curl_ssl_set_engine(x,y) CURLE_NOT_BUILT_IN +#define Curl_ssl_set_engine(x, y) CURLE_NOT_BUILT_IN #define Curl_ssl_set_engine_default(x) CURLE_NOT_BUILT_IN #define Curl_ssl_engines_list(x) NULL #define Curl_ssl_free_certinfo(x) Curl_nop_stmt -#define Curl_ssl_random(x,y,z) ((void)x, CURLE_NOT_BUILT_IN) +#define Curl_ssl_random(x, y, z) ((void)x, CURLE_NOT_BUILT_IN) #define Curl_ssl_cert_status_request() FALSE -#define Curl_ssl_supports(a,b) FALSE -#define Curl_ssl_cfilter_add(a,b,c) CURLE_NOT_BUILT_IN -#define Curl_ssl_cfilter_remove(a,b,c) CURLE_OK -#define Curl_ssl_cf_get_config(a,b) NULL +#define Curl_ssl_supports(a, b) FALSE +#define Curl_ssl_cfilter_add(a, b, c) CURLE_NOT_BUILT_IN +#define Curl_ssl_cfilter_remove(a, b, c) CURLE_OK +#define Curl_ssl_cf_get_config(a, b) NULL #define Curl_ssl_cf_get_primary_config(a) NULL #endif diff --git a/lib/vtls/vtls_int.h b/lib/vtls/vtls_int.h index 8bf6c6c64be9..cdb07b5f2bee 100644 --- a/lib/vtls/vtls_int.h +++ b/lib/vtls/vtls_int.h @@ -24,7 +24,9 @@ * ***************************************************************************/ #include "../curl_setup.h" + #include "../cfilters.h" +#include "../select.h" #include "../urldata.h" #include "vtls.h" @@ -71,8 +73,7 @@ CURLcode Curl_alpn_set_negotiated(struct Curl_cfilter *cf, const unsigned char *proto, size_t proto_len); -bool Curl_alpn_contains_proto(const struct alpn_spec *spec, - const char *proto); +bool Curl_alpn_contains_proto(const struct alpn_spec *spec, const char *proto); /* enum for the nonblocking SSL connection state machine */ typedef enum { @@ -99,11 +100,11 @@ typedef enum { } ssl_earlydata_state; #define CURL_SSL_IO_NEED_NONE (0) -#define CURL_SSL_IO_NEED_RECV (1<<0) -#define CURL_SSL_IO_NEED_SEND (1<<1) +#define CURL_SSL_IO_NEED_RECV (1 << 0) +#define CURL_SSL_IO_NEED_SEND (1 << 1) /* Max earlydata payload we want to send */ -#define CURL_SSL_EARLY_MAX (64*1024) +#define CURL_SSL_EARLY_MAX (64 * 1024) /* Information in each SSL cfilter context: cf->ctx */ struct ssl_connect_data { @@ -130,11 +131,8 @@ struct ssl_connect_data { BIT(input_pending); /* data for SSL_read() may be available */ }; - #undef CF_CTX_CALL_DATA -#define CF_CTX_CALL_DATA(cf) \ - ((struct ssl_connect_data *)(cf)->ctx)->call_data - +#define CF_CTX_CALL_DATA(cf) ((struct ssl_connect_data *)(cf)->ctx)->call_data /* Definitions for SSL Implementations */ @@ -157,8 +155,7 @@ struct Curl_ssl { /* data_pending() shall return TRUE when it wants to get called again to drain internal buffers and deliver data instead of waiting for the socket to get readable */ - bool (*data_pending)(struct Curl_cfilter *cf, - const struct Curl_easy *data); + bool (*data_pending)(struct Curl_cfilter *cf, const struct Curl_easy *data); /* return 0 if a find random is filled in */ CURLcode (*random)(struct Curl_easy *data, unsigned char *entropy, @@ -181,7 +178,7 @@ struct Curl_ssl { struct curl_slist *(*engines_list)(struct Curl_easy *data); CURLcode (*sha256sum)(const unsigned char *input, size_t inputlen, - unsigned char *sha256sum, size_t sha256sumlen); + unsigned char *sha256sum, size_t sha256sumlen); CURLcode (*recv_plain)(struct Curl_cfilter *cf, struct Curl_easy *data, char *buf, size_t len, size_t *pnread); CURLcode (*send_plain)(struct Curl_cfilter *cf, struct Curl_easy *data, @@ -189,7 +186,6 @@ struct Curl_ssl { CURLcode (*get_channel_binding)(struct Curl_easy *data, int sockindex, struct dynbuf *binding); - }; extern const struct Curl_ssl *Curl_ssl; diff --git a/lib/vtls/vtls_scache.c b/lib/vtls/vtls_scache.c index 763b474cfc7d..ea4ea4e68efa 100644 --- a/lib/vtls/vtls_scache.c +++ b/lib/vtls/vtls_scache.c @@ -41,16 +41,10 @@ #include "../strcase.h" #include "../url.h" #include "../llist.h" -#include "../share.h" +#include "../curl_share.h" #include "../curl_trc.h" #include "../curl_sha256.h" #include "../rand.h" -#include "../curlx/warnless.h" -#include "../strdup.h" - -/* The last #include files should be: */ -#include "../curl_memory.h" -#include "../memdebug.h" static bool cf_ssl_peer_key_is_global(const char *peer_key); @@ -105,42 +99,40 @@ static void cf_ssl_scache_session_ldestroy(void *udata, void *obj) { struct Curl_ssl_session *s = obj; (void)udata; - free(CURL_UNCONST(s->sdata)); - free(CURL_UNCONST(s->quic_tp)); - free((void *)s->alpn); - free(s); + curlx_free(CURL_UNCONST(s->sdata)); + curlx_free(CURL_UNCONST(s->quic_tp)); + curlx_free((void *)s->alpn); + curlx_free(s); } -CURLcode -Curl_ssl_session_create(void *sdata, size_t sdata_len, - int ietf_tls_id, const char *alpn, - curl_off_t valid_until, size_t earlydata_max, - struct Curl_ssl_session **psession) +CURLcode Curl_ssl_session_create(void *sdata, size_t sdata_len, + int ietf_tls_id, const char *alpn, + curl_off_t valid_until, size_t earlydata_max, + struct Curl_ssl_session **psession) { return Curl_ssl_session_create2(sdata, sdata_len, ietf_tls_id, alpn, valid_until, earlydata_max, NULL, 0, psession); } -CURLcode -Curl_ssl_session_create2(void *sdata, size_t sdata_len, - int ietf_tls_id, const char *alpn, - curl_off_t valid_until, size_t earlydata_max, - unsigned char *quic_tp, size_t quic_tp_len, - struct Curl_ssl_session **psession) +CURLcode Curl_ssl_session_create2(void *sdata, size_t sdata_len, + int ietf_tls_id, const char *alpn, + curl_off_t valid_until, size_t earlydata_max, + unsigned char *quic_tp, size_t quic_tp_len, + struct Curl_ssl_session **psession) { struct Curl_ssl_session *s; if(!sdata || !sdata_len) { - free(sdata); + curlx_free(sdata); return CURLE_BAD_FUNCTION_ARGUMENT; } *psession = NULL; - s = calloc(1, sizeof(*s)); + s = curlx_calloc(1, sizeof(*s)); if(!s) { - free(sdata); - free(quic_tp); + curlx_free(sdata); + curlx_free(quic_tp); return CURLE_OUT_OF_MEMORY; } @@ -152,7 +144,7 @@ Curl_ssl_session_create2(void *sdata, size_t sdata_len, s->quic_tp = quic_tp; s->quic_tp_len = quic_tp_len; if(alpn) { - s->alpn = strdup(alpn); + s->alpn = curlx_strdup(alpn); if(!s->alpn) { cf_ssl_scache_session_ldestroy(NULL, s); return CURLE_OUT_OF_MEMORY; @@ -232,7 +224,7 @@ cf_ssl_scache_peer_init(struct Curl_ssl_scache_peer *peer, DEBUGASSERT(!peer->ssl_peer_key); if(ssl_peer_key) { - peer->ssl_peer_key = strdup(ssl_peer_key); + peer->ssl_peer_key = curlx_strdup(ssl_peer_key); if(!peer->ssl_peer_key) goto out; peer->hmac_set = FALSE; @@ -247,17 +239,17 @@ cf_ssl_scache_peer_init(struct Curl_ssl_scache_peer *peer, goto out; } if(clientcert) { - peer->clientcert = strdup(clientcert); + peer->clientcert = curlx_strdup(clientcert); if(!peer->clientcert) goto out; } if(srp_username) { - peer->srp_username = strdup(srp_username); + peer->srp_username = curlx_strdup(srp_username); if(!peer->srp_username) goto out; } if(srp_password) { - peer->srp_password = strdup(srp_password); + peer->srp_password = curlx_strdup(srp_password); if(!peer->srp_password) goto out; } @@ -316,18 +308,18 @@ CURLcode Curl_ssl_scache_create(size_t max_peers, size_t i; *pscache = NULL; - peers = calloc(max_peers, sizeof(*peers)); + peers = curlx_calloc(max_peers, sizeof(*peers)); if(!peers) return CURLE_OUT_OF_MEMORY; - scache = calloc(1, sizeof(*scache)); + scache = curlx_calloc(1, sizeof(*scache)); if(!scache) { - free(peers); + curlx_free(peers); return CURLE_OUT_OF_MEMORY; } scache->magic = CURL_SCACHE_MAGIC; - scache->default_lifetime_secs = (24*60*60); /* 1 day */ + scache->default_lifetime_secs = (24 * 60 * 60); /* 1 day */ scache->peer_count = max_peers; scache->peers = peers; scache->age = 1; @@ -349,9 +341,18 @@ void Curl_ssl_scache_destroy(struct Curl_ssl_scache *scache) for(i = 0; i < scache->peer_count; ++i) { cf_ssl_scache_clear_peer(&scache->peers[i]); } - free(scache->peers); - free(scache); + curlx_free(scache->peers); + curlx_free(scache); + } +} + +bool Curl_ssl_scache_use(struct Curl_cfilter *cf, struct Curl_easy *data) +{ + if(cf_ssl_scache_get(data)) { + struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); + return ssl_config ? ssl_config->primary.cache_session : FALSE; } + return FALSE; } /* Lock shared SSL session data */ @@ -378,10 +379,7 @@ static CURLcode cf_ssl_peer_key_add_path(struct dynbuf *buf, * valid when used in another process with different CWD. However, * when a path does not exist, this does not work. Then, we add * the path as is. */ -#ifdef UNDER_CE - (void)is_local; - return curlx_dyn_addf(buf, ":%s-%s", name, path); -#elif defined(_WIN32) +#ifdef _WIN32 char abspath[_MAX_PATH]; if(_fullpath(abspath, path, _MAX_PATH)) return curlx_dyn_addf(buf, ":%s-%s", name, abspath); @@ -391,7 +389,8 @@ static CURLcode cf_ssl_peer_key_add_path(struct dynbuf *buf, char *abspath = realpath(path, NULL); if(abspath) { CURLcode r = curlx_dyn_addf(buf, ":%s-%s", name, abspath); - (free)(abspath); /* allocated by libc, free without memdebug */ + /* !checksrc! disable BANNEDFUNC 1 */ + free(abspath); /* allocated by libc, free without memdebug */ return r; } *is_local = TRUE; @@ -505,7 +504,7 @@ CURLcode Curl_ssl_peer_key_make(struct Curl_cfilter *cf, if(ssl->version || ssl->version_max) { r = curlx_dyn_addf(&buf, ":TLSVER-%d-%d", ssl->version, - (ssl->version_max >> 16)); + (ssl->version_max >> 16)); if(r) goto out; } @@ -614,19 +613,18 @@ static bool cf_ssl_scache_match_auth(struct Curl_ssl_scache_peer *peer, else if(!Curl_safecmp(peer->clientcert, conn_config->clientcert)) return FALSE; #ifdef USE_TLS_SRP - if(Curl_timestrcmp(peer->srp_username, conn_config->username) || - Curl_timestrcmp(peer->srp_password, conn_config->password)) - return FALSE; + if(Curl_timestrcmp(peer->srp_username, conn_config->username) || + Curl_timestrcmp(peer->srp_password, conn_config->password)) + return FALSE; #endif return TRUE; } -static CURLcode -cf_ssl_find_peer_by_key(struct Curl_easy *data, - struct Curl_ssl_scache *scache, - const char *ssl_peer_key, - struct ssl_primary_config *conn_config, - struct Curl_ssl_scache_peer **ppeer) +static CURLcode cf_ssl_find_peer_by_key(struct Curl_easy *data, + struct Curl_ssl_scache *scache, + const char *ssl_peer_key, + struct ssl_primary_config *conn_config, + struct Curl_ssl_scache_peer **ppeer) { size_t i, peer_key_len = 0; CURLcode result = CURLE_OK; @@ -670,7 +668,7 @@ cf_ssl_find_peer_by_key(struct Curl_easy *data, /* remember peer_key for future lookups */ CURL_TRC_SSLS(data, "peer entry %zu key recovered: %s", i, ssl_peer_key); - scache->peers[i].ssl_peer_key = strdup(ssl_peer_key); + scache->peers[i].ssl_peer_key = curlx_strdup(ssl_peer_key); if(!scache->peers[i].ssl_peer_key) { result = CURLE_OUT_OF_MEMORY; goto out; @@ -716,12 +714,11 @@ cf_ssl_get_free_peer(struct Curl_ssl_scache *scache) return peer; } -static CURLcode -cf_ssl_add_peer(struct Curl_easy *data, - struct Curl_ssl_scache *scache, - const char *ssl_peer_key, - struct ssl_primary_config *conn_config, - struct Curl_ssl_scache_peer **ppeer) +static CURLcode cf_ssl_add_peer(struct Curl_easy *data, + struct Curl_ssl_scache *scache, + const char *ssl_peer_key, + struct ssl_primary_config *conn_config, + struct Curl_ssl_scache_peer **ppeer) { struct Curl_ssl_scache_peer *peer = NULL; CURLcode result = CURLE_OK; @@ -998,7 +995,7 @@ void Curl_ssl_scache_remove_all(struct Curl_cfilter *cf, #ifdef USE_SSLS_EXPORT -#define CURL_SSL_TICKET_MAX (16*1024) +#define CURL_SSL_TICKET_MAX (16 * 1024) static CURLcode cf_ssl_scache_peer_set_hmac(struct Curl_ssl_scache_peer *peer) { diff --git a/lib/vtls/vtls_scache.h b/lib/vtls/vtls_scache.h index deedccfe8c66..67049462a859 100644 --- a/lib/vtls/vtls_scache.h +++ b/lib/vtls/vtls_scache.h @@ -37,8 +37,8 @@ struct ssl_peer; /* RFC 8446 (TLSv1.3) restrict lifetime to one week max, for * other, less secure versions, we restrict it to a day */ -#define CURL_SCACHE_MAX_13_LIFETIME_SEC (60*60*24*7) -#define CURL_SCACHE_MAX_12_LIFETIME_SEC (60*60*24) +#define CURL_SCACHE_MAX_13_LIFETIME_SEC (60 * 60 * 24 * 7) +#define CURL_SCACHE_MAX_12_LIFETIME_SEC (60 * 60 * 24) /* Create a session cache for up to max_peers endpoints with a total * of up to max_sessions SSL sessions per peer */ @@ -65,6 +65,12 @@ CURLcode Curl_ssl_peer_key_make(struct Curl_cfilter *cf, const char *tls_id, char **ppeer_key); +/* Return if there is a session cache shall be used. + * An ssl session might not be configured or not available for + * "connect-only" transfers. + */ +bool Curl_ssl_scache_use(struct Curl_cfilter *cf, struct Curl_easy *data); + /* Lock session cache mutex. * Call this before calling other Curl_ssl_*session* functions * Caller should unlock this mutex as soon as possible, as it may block @@ -136,22 +142,18 @@ struct Curl_ssl_session { * in case this is not known. * @param psession on return the scached session instance created */ -CURLcode -Curl_ssl_session_create(void *sdata, size_t sdata_len, - int ietf_tls_id, const char *alpn, - curl_off_t valid_until, - size_t earlydata_max, - struct Curl_ssl_session **psession); +CURLcode Curl_ssl_session_create(void *sdata, size_t sdata_len, + int ietf_tls_id, const char *alpn, + curl_off_t valid_until, size_t earlydata_max, + struct Curl_ssl_session **psession); /* Variation of session creation with quic transport parameter bytes, * Takes ownership of `quic_tp` regardless of return code. */ -CURLcode -Curl_ssl_session_create2(void *sdata, size_t sdata_len, - int ietf_tls_id, const char *alpn, - curl_off_t valid_until, - size_t earlydata_max, - unsigned char *quic_tp, size_t quic_tp_len, - struct Curl_ssl_session **psession); +CURLcode Curl_ssl_session_create2(void *sdata, size_t sdata_len, + int ietf_tls_id, const char *alpn, + curl_off_t valid_until, size_t earlydata_max, + unsigned char *quic_tp, size_t quic_tp_len, + struct Curl_ssl_session **psession); /* Destroy a `session` instance. Can be called with NULL. * Does NOT need locking. */ diff --git a/lib/vtls/vtls_spack.c b/lib/vtls/vtls_spack.c index 10d16f213d4f..ac289f1b2f69 100644 --- a/lib/vtls/vtls_spack.c +++ b/lib/vtls/vtls_spack.c @@ -32,21 +32,6 @@ #include "vtls_spack.h" #include "../strdup.h" -/* The last #include files should be: */ -#include "../curl_memory.h" -#include "../memdebug.h" - -#ifdef _MSC_VER -#if _MSC_VER >= 1600 -#include -#else -typedef unsigned char uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int64 uint64_t; -#endif -#endif /* _MSC_VER */ - #ifndef UINT16_MAX #define UINT16_MAX 0xffff #endif @@ -67,8 +52,8 @@ static CURLcode spack_enc8(struct dynbuf *buf, uint8_t b) return curlx_dyn_addn(buf, &b, 1); } -static CURLcode -spack_dec8(uint8_t *val, const uint8_t **src, const uint8_t *end) +static CURLcode spack_dec8(uint8_t *val, const uint8_t **src, + const uint8_t *end) { if(end - *src < 1) return CURLE_READ_ERROR; @@ -85,8 +70,8 @@ static CURLcode spack_enc16(struct dynbuf *buf, uint16_t val) return curlx_dyn_addn(buf, nval, sizeof(nval)); } -static CURLcode -spack_dec16(uint16_t *val, const uint8_t **src, const uint8_t *end) +static CURLcode spack_dec16(uint16_t *val, const uint8_t **src, + const uint8_t *end) { if(end - *src < 2) return CURLE_READ_ERROR; @@ -105,8 +90,8 @@ static CURLcode spack_enc32(struct dynbuf *buf, uint32_t val) return curlx_dyn_addn(buf, nval, sizeof(nval)); } -static CURLcode -spack_dec32(uint32_t *val, const uint8_t **src, const uint8_t *end) +static CURLcode spack_dec32(uint32_t *val, const uint8_t **src, + const uint8_t *end) { if(end - *src < 4) return CURLE_READ_ERROR; @@ -122,7 +107,7 @@ static CURLcode spack_enc64(struct dynbuf *buf, uint64_t val) nval[0] = (uint8_t)(val >> 56); nval[1] = (uint8_t)(val >> 48); nval[2] = (uint8_t)(val >> 40); - nval[3] = (uint8_t)(val >> 32); \ + nval[3] = (uint8_t)(val >> 32); nval[4] = (uint8_t)(val >> 24); nval[5] = (uint8_t)(val >> 16); nval[6] = (uint8_t)(val >> 8); @@ -130,8 +115,8 @@ static CURLcode spack_enc64(struct dynbuf *buf, uint64_t val) return curlx_dyn_addn(buf, nval, sizeof(nval)); } -static CURLcode -spack_dec64(uint64_t *val, const uint8_t **src, const uint8_t *end) +static CURLcode spack_dec64(uint64_t *val, const uint8_t **src, + const uint8_t *end) { if(end - *src < 8) return CURLE_READ_ERROR; @@ -156,8 +141,8 @@ static CURLcode spack_encstr16(struct dynbuf *buf, const char *s) return r; } -static CURLcode -spack_decstr16(char **val, const uint8_t **src, const uint8_t *end) +static CURLcode spack_decstr16(char **val, const uint8_t **src, + const uint8_t *end) { uint16_t slen; CURLcode r; @@ -173,8 +158,8 @@ spack_decstr16(char **val, const uint8_t **src, const uint8_t *end) return *val ? CURLE_OK : CURLE_OUT_OF_MEMORY; } -static CURLcode spack_encdata16(struct dynbuf *buf, - const uint8_t *data, size_t data_len) +static CURLcode spack_encdata16(struct dynbuf *buf, const uint8_t *data, + size_t data_len) { CURLcode r; if(data_len > UINT16_MAX) @@ -186,9 +171,8 @@ static CURLcode spack_encdata16(struct dynbuf *buf, return r; } -static CURLcode -spack_decdata16(uint8_t **val, size_t *val_len, - const uint8_t **src, const uint8_t *end) +static CURLcode spack_decdata16(uint8_t **val, size_t *val_len, + const uint8_t **src, const uint8_t *end) { uint16_t data_len; CURLcode r; @@ -278,7 +262,7 @@ CURLcode Curl_ssl_session_unpack(struct Curl_easy *data, goto out; } - s = calloc(1, sizeof(*s)); + s = curlx_calloc(1, sizeof(*s)); if(!s) { r = CURLE_OUT_OF_MEMORY; goto out; diff --git a/lib/vtls/wolfssl.c b/lib/vtls/wolfssl.c index d4a0e066fa03..3ccd0917a4fe 100644 --- a/lib/vtls/wolfssl.c +++ b/lib/vtls/wolfssl.c @@ -36,7 +36,6 @@ #include #include - #if LIBWOLFSSL_VERSION_HEX < 0x03004006 /* wolfSSL 3.4.6 (2015) */ #error "wolfSSL version should be at least 3.4.6" #endif @@ -54,35 +53,22 @@ #endif #endif -#include - #include "../urldata.h" -#include "../sendf.h" -#include "../curlx/inet_pton.h" +#include "../curl_trc.h" #include "vtls.h" #include "vtls_int.h" #include "vtls_scache.h" #include "keylog.h" -#include "../parsedate.h" #include "../connect.h" /* for the connect timeout */ #include "../progress.h" -#include "../select.h" #include "../strdup.h" +#include "../curlx/strcopy.h" #include "x509asn1.h" -#include "../multiif.h" #include #include #include "wolfssl.h" -/* The last #include files should be: */ -#include "../curl_memory.h" -#include "../memdebug.h" - -#ifdef HAVE_WOLFSSL_CTX_GENERATEECHCONFIG -#define USE_ECH_WOLFSSL -#endif - /* KEEP_PEER_CERT is a product of the presence of build time symbol OPENSSL_EXTRA without NO_CERTS, depending on the version. KEEP_PEER_CERT is in wolfSSL's settings.h, and the latter two are build time symbols in @@ -131,9 +117,9 @@ static CURLcode wssl_connect(struct Curl_cfilter *cf, * (--enable-opensslextra or --enable-all). */ #if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13) -static int -wssl_tls13_secret_callback(SSL *ssl, int id, const unsigned char *secret, - int secretSz, void *ctx) +static int wssl_tls13_secret_callback(SSL *ssl, int id, + const unsigned char *secret, + int secretSz, void *ctx) { const char *label; unsigned char client_random[SSL3_RANDOM_SIZE]; @@ -313,8 +299,7 @@ static long wssl_bio_cf_ctrl(WOLFSSL_BIO *bio, int cmd, long num, void *ptr) return ret; } -static int wssl_bio_cf_out_write(WOLFSSL_BIO *bio, - const char *buf, int blen) +static int wssl_bio_cf_out_write(WOLFSSL_BIO *bio, const char *buf, int blen) { struct Curl_cfilter *cf = wolfSSL_BIO_get_data(bio); struct ssl_connect_data *connssl = cf->ctx; @@ -334,7 +319,8 @@ static int wssl_bio_cf_out_write(WOLFSSL_BIO *bio, skiplen = (ssize_t)(blen - wssl->io_send_blocked_len); blen = wssl->io_send_blocked_len; } - result = Curl_conn_cf_send(cf->next, data, buf, blen, FALSE, &nwritten); + result = Curl_conn_cf_send(cf->next, data, + (const uint8_t *)buf, blen, FALSE, &nwritten); wssl->io_result = result; CURL_TRC_CF(data, cf, "bio_write(len=%d) -> %d, %zu", blen, result, nwritten); @@ -357,7 +343,7 @@ static int wssl_bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen) struct ssl_connect_data *connssl = cf->ctx; struct wssl_ctx *wssl = (struct wssl_ctx *)connssl->backend; struct Curl_easy *data = CF_DATA_CURRENT(cf); - size_t nread; + size_t nread = 0; CURLcode result = CURLE_OK; DEBUGASSERT(data); @@ -395,20 +381,24 @@ static int wssl_bio_cf_in_read(WOLFSSL_BIO *bio, char *buf, int blen) static WOLFSSL_BIO_METHOD *wssl_bio_cf_method = NULL; -static void wssl_bio_cf_init_methods(void) +static int wssl_bio_cf_init_methods(void) { wssl_bio_cf_method = wolfSSL_BIO_meth_new(WOLFSSL_BIO_MEMORY, - "wolfSSL CF BIO"); + "wolfSSL CF BIO"); + if(!wssl_bio_cf_method) + return FALSE; /* error */ wolfSSL_BIO_meth_set_write(wssl_bio_cf_method, &wssl_bio_cf_out_write); wolfSSL_BIO_meth_set_read(wssl_bio_cf_method, &wssl_bio_cf_in_read); wolfSSL_BIO_meth_set_ctrl(wssl_bio_cf_method, &wssl_bio_cf_ctrl); wolfSSL_BIO_meth_set_create(wssl_bio_cf_method, &wssl_bio_cf_create); wolfSSL_BIO_meth_set_destroy(wssl_bio_cf_method, &wssl_bio_cf_destroy); + return TRUE; /* fine */ } static void wssl_bio_cf_free_methods(void) { wolfSSL_BIO_meth_free(wssl_bio_cf_method); + wssl_bio_cf_method = NULL; } #else /* USE_BIO_CHAIN */ @@ -418,6 +408,7 @@ static void wssl_bio_cf_free_methods(void) #endif /* !USE_BIO_CHAIN */ +#ifdef HAVE_EX_DATA CURLcode Curl_wssl_cache_session(struct Curl_cfilter *cf, struct Curl_easy *data, const char *ssl_peer_key, @@ -429,7 +420,7 @@ CURLcode Curl_wssl_cache_session(struct Curl_cfilter *cf, { CURLcode result = CURLE_OK; struct Curl_ssl_session *sc_session = NULL; - unsigned char *sdata = NULL, *qtp_clone = NULL; + unsigned char *sdata = NULL, *sdata_ptr, *qtp_clone = NULL; unsigned int sdata_len; unsigned int earlydata_max = 0; @@ -442,13 +433,15 @@ CURLcode Curl_wssl_cache_session(struct Curl_cfilter *cf, result = CURLE_FAILED_INIT; goto out; } - sdata = calloc(1, sdata_len); + sdata = sdata_ptr = curlx_calloc(1, sdata_len); if(!sdata) { failf(data, "unable to allocate session buffer of %u bytes", sdata_len); result = CURLE_OUT_OF_MEMORY; goto out; } - sdata_len = wolfSSL_i2d_SSL_SESSION(session, &sdata); + /* wolfSSL right now does not change the last parameter here, but it + * might one day decide to do so for OpenSSL compatibility. */ + sdata_len = wolfSSL_i2d_SSL_SESSION(session, &sdata_ptr); if(sdata_len <= 0) { CURL_TRC_CF(data, cf, "fail to serialize session: %u", sdata_len); result = CURLE_FAILED_INIT; @@ -457,7 +450,7 @@ CURLcode Curl_wssl_cache_session(struct Curl_cfilter *cf, if(quic_tp && quic_tp_len) { qtp_clone = Curl_memdup0((char *)quic_tp, quic_tp_len); if(!qtp_clone) { - free(sdata); + curlx_free(sdata); return CURLE_OUT_OF_MEMORY; } } @@ -478,7 +471,7 @@ CURLcode Curl_wssl_cache_session(struct Curl_cfilter *cf, } out: - free(sdata); + curlx_free(sdata); return result; } @@ -486,7 +479,7 @@ static int wssl_vtls_new_session_cb(WOLFSSL *ssl, WOLFSSL_SESSION *session) { struct Curl_cfilter *cf; - cf = (struct Curl_cfilter*)wolfSSL_get_app_data(ssl); + cf = (struct Curl_cfilter *)wolfSSL_get_app_data(ssl); DEBUGASSERT(cf != NULL); if(cf && session) { struct ssl_connect_data *connssl = cf->ctx; @@ -501,6 +494,7 @@ static int wssl_vtls_new_session_cb(WOLFSSL *ssl, WOLFSSL_SESSION *session) } return 0; } +#endif static CURLcode wssl_on_session_reuse(struct Curl_cfilter *cf, struct Curl_easy *data, @@ -534,8 +528,8 @@ static CURLcode wssl_on_session_reuse(struct Curl_cfilter *cf, connssl->earlydata_state = ssl_earlydata_await; connssl->state = ssl_connection_deferred; result = Curl_alpn_set_negotiated(cf, data, connssl, - (const unsigned char *)scs->alpn, - scs->alpn ? strlen(scs->alpn) : 0); + (const unsigned char *)scs->alpn, + scs->alpn ? strlen(scs->alpn) : 0); *do_early_data = !result; } return result; @@ -577,8 +571,10 @@ wssl_setup_session(struct Curl_cfilter *cf, bool do_early_data = FALSE; if(sess_reuse_cb) { result = sess_reuse_cb(cf, data, alpns, scs, &do_early_data); - if(result) - goto out; + if(result) { + wolfSSL_SESSION_free(session); + goto out; + } } #ifdef WOLFSSL_EARLY_DATA if(do_early_data) { @@ -637,7 +633,7 @@ static CURLcode wssl_populate_x509_store(struct Curl_cfilter *cf, } #else infof(data, "ignoring native CA option because wolfSSL was built without " - "native CA support"); + "native CA support"); #endif } #endif /* !NO_FILESYSTEM */ @@ -685,7 +681,7 @@ static CURLcode wssl_populate_x509_store(struct Curl_cfilter *cf, /* Just continue with a warning if no strict certificate verification is required. */ infof(data, "error setting certificate verify locations," - " continuing anyway:"); + " continuing anyway:"); } } else { @@ -704,32 +700,30 @@ static CURLcode wssl_populate_x509_store(struct Curl_cfilter *cf, #define MPROTO_WSSL_X509_KEY "tls:wssl:x509:share" struct wssl_x509_share { - char *CAfile; /* CAfile path used to generate X509 store */ + char *CAfile; /* CAfile path used to generate X509 store */ WOLFSSL_X509_STORE *store; /* cached X509 store or NULL if none */ - struct curltime time; /* when the cached store was created */ + struct curltime time; /* when the cached store was created */ }; static void wssl_x509_share_free(void *key, size_t key_len, void *p) { struct wssl_x509_share *share = p; - DEBUGASSERT(key_len == (sizeof(MPROTO_WSSL_X509_KEY)-1)); + DEBUGASSERT(key_len == (sizeof(MPROTO_WSSL_X509_KEY) - 1)); DEBUGASSERT(!memcmp(MPROTO_WSSL_X509_KEY, key, key_len)); (void)key; (void)key_len; if(share->store) { wolfSSL_X509_STORE_free(share->store); } - free(share->CAfile); - free(share); + curlx_free(share->CAfile); + curlx_free(share); } -static bool -wssl_cached_x509_store_expired(const struct Curl_easy *data, - const struct wssl_x509_share *mb) +static bool wssl_cached_x509_store_expired(struct Curl_easy *data, + const struct wssl_x509_share *mb) { const struct ssl_general_config *cfg = &data->set.general_ssl; - struct curltime now = curlx_now(); - timediff_t elapsed_ms = curlx_timediff(now, mb->time); + timediff_t elapsed_ms = curlx_ptimediff_ms(Curl_pgrs_now(data), &mb->time); timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000; if(timeout_ms < 0) @@ -738,9 +732,8 @@ wssl_cached_x509_store_expired(const struct Curl_easy *data, return elapsed_ms >= timeout_ms; } -static bool -wssl_cached_x509_store_different(struct Curl_cfilter *cf, - const struct wssl_x509_share *mb) +static bool wssl_cached_x509_store_different(struct Curl_cfilter *cf, + const struct wssl_x509_share *mb) { struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); if(!mb->CAfile || !conn_config->CAfile) @@ -750,7 +743,7 @@ wssl_cached_x509_store_different(struct Curl_cfilter *cf, } static WOLFSSL_X509_STORE *wssl_get_cached_x509_store(struct Curl_cfilter *cf, - const struct Curl_easy *data) + struct Curl_easy *data) { struct Curl_multi *multi = data->multi; struct wssl_x509_share *share; @@ -759,7 +752,7 @@ static WOLFSSL_X509_STORE *wssl_get_cached_x509_store(struct Curl_cfilter *cf, DEBUGASSERT(multi); share = multi ? Curl_hash_pick(&multi->proto_hash, CURL_UNCONST(MPROTO_WSSL_X509_KEY), - sizeof(MPROTO_WSSL_X509_KEY)-1) : NULL; + sizeof(MPROTO_WSSL_X509_KEY) - 1) : NULL; if(share && share->store && !wssl_cached_x509_store_expired(data, share) && !wssl_cached_x509_store_different(cf, share)) { @@ -770,7 +763,7 @@ static WOLFSSL_X509_STORE *wssl_get_cached_x509_store(struct Curl_cfilter *cf, } static void wssl_set_cached_x509_store(struct Curl_cfilter *cf, - const struct Curl_easy *data, + struct Curl_easy *data, WOLFSSL_X509_STORE *store) { struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); @@ -782,17 +775,17 @@ static void wssl_set_cached_x509_store(struct Curl_cfilter *cf, return; share = Curl_hash_pick(&multi->proto_hash, CURL_UNCONST(MPROTO_WSSL_X509_KEY), - sizeof(MPROTO_WSSL_X509_KEY)-1); + sizeof(MPROTO_WSSL_X509_KEY) - 1); if(!share) { - share = calloc(1, sizeof(*share)); + share = curlx_calloc(1, sizeof(*share)); if(!share) return; if(!Curl_hash_add2(&multi->proto_hash, CURL_UNCONST(MPROTO_WSSL_X509_KEY), - sizeof(MPROTO_WSSL_X509_KEY)-1, + sizeof(MPROTO_WSSL_X509_KEY) - 1, share, wssl_x509_share_free)) { - free(share); + curlx_free(share); return; } } @@ -801,7 +794,7 @@ static void wssl_set_cached_x509_store(struct Curl_cfilter *cf, char *CAfile = NULL; if(conn_config->CAfile) { - CAfile = strdup(conn_config->CAfile); + CAfile = curlx_strdup(conn_config->CAfile); if(!CAfile) { wolfSSL_X509_STORE_free(store); return; @@ -810,10 +803,10 @@ static void wssl_set_cached_x509_store(struct Curl_cfilter *cf, if(share->store) { wolfSSL_X509_STORE_free(share->store); - free(share->CAfile); + curlx_free(share->CAfile); } - share->time = curlx_now(); + share->time = *Curl_pgrs_now(data); share->store = store; share->CAfile = CAfile; } @@ -864,17 +857,16 @@ CURLcode Curl_wssl_setup_x509_store(struct Curl_cfilter *cf, } } else { - /* We never share the CTX's store, use it. */ - WOLFSSL_X509_STORE *store = wolfSSL_CTX_get_cert_store(wssl->ssl_ctx); - result = wssl_populate_x509_store(cf, data, store, wssl); + /* We never share the CTX's store, use it. */ + WOLFSSL_X509_STORE *store = wolfSSL_CTX_get_cert_store(wssl->ssl_ctx); + result = wssl_populate_x509_store(cf, data, store, wssl); } return result; } #ifdef WOLFSSL_TLS13 -static CURLcode -wssl_add_default_ciphers(bool tls13, struct dynbuf *buf) +static CURLcode wssl_add_default_ciphers(bool tls13, struct dynbuf *buf) { int i; char *str; @@ -902,8 +894,7 @@ wssl_add_default_ciphers(bool tls13, struct dynbuf *buf) /* 4.2.0 (2019) */ #if LIBWOLFSSL_VERSION_HEX < 0x04002000 || !defined(OPENSSL_EXTRA) -static int -wssl_legacy_CTX_set_min_proto_version(WOLFSSL_CTX* ctx, int version) +static int wssl_legacy_CTX_set_min_proto_version(WOLFSSL_CTX *ctx, int version) { int res; switch(version) { @@ -930,8 +921,8 @@ wssl_legacy_CTX_set_min_proto_version(WOLFSSL_CTX* ctx, int version) } return res; } -static int -wssl_legacy_CTX_set_max_proto_version(WOLFSSL_CTX* ctx, int version) + +static int wssl_legacy_CTX_set_max_proto_version(WOLFSSL_CTX *ctx, int version) { (void)ctx, (void)version; return WOLFSSL_NOT_IMPLEMENTED; @@ -1037,66 +1028,72 @@ static CURLcode client_certificate(struct Curl_easy *data, static CURLcode ssl_version(struct Curl_easy *data, struct ssl_primary_config *conn_config, - struct wssl_ctx *wctx) + struct wssl_ctx *wctx, + int *min_version, int *max_version) { int res; + *min_version = *max_version = 0; switch(conn_config->version) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: case CURL_SSLVERSION_TLSv1_0: - res = wolfSSL_CTX_set_min_proto_version(wctx->ssl_ctx, TLS1_VERSION); + *min_version = TLS1_VERSION; break; case CURL_SSLVERSION_TLSv1_1: - res = wolfSSL_CTX_set_min_proto_version(wctx->ssl_ctx, TLS1_1_VERSION); + *min_version = TLS1_1_VERSION; break; case CURL_SSLVERSION_TLSv1_2: - res = wolfSSL_CTX_set_min_proto_version(wctx->ssl_ctx, TLS1_2_VERSION); + *min_version = TLS1_2_VERSION; break; #ifdef WOLFSSL_TLS13 case CURL_SSLVERSION_TLSv1_3: - res = wolfSSL_CTX_set_min_proto_version(wctx->ssl_ctx, TLS1_3_VERSION); + *min_version = TLS1_3_VERSION; break; #endif default: failf(data, "wolfSSL: unsupported minimum TLS version value"); return CURLE_SSL_CONNECT_ERROR; } - if(res != WOLFSSL_SUCCESS) { - failf(data, "wolfSSL: failed set the minimum TLS version"); - return CURLE_SSL_CONNECT_ERROR; - } switch(conn_config->version_max) { #ifdef WOLFSSL_TLS13 case CURL_SSLVERSION_MAX_TLSv1_3: - res = wolfSSL_CTX_set_max_proto_version(wctx->ssl_ctx, TLS1_3_VERSION); + *max_version = TLS1_3_VERSION; break; #endif case CURL_SSLVERSION_MAX_TLSv1_2: - res = wolfSSL_CTX_set_max_proto_version(wctx->ssl_ctx, TLS1_2_VERSION); + *max_version = TLS1_2_VERSION; break; case CURL_SSLVERSION_MAX_TLSv1_1: - res = wolfSSL_CTX_set_max_proto_version(wctx->ssl_ctx, TLS1_1_VERSION); + *max_version = TLS1_1_VERSION; break; case CURL_SSLVERSION_MAX_TLSv1_0: - res = wolfSSL_CTX_set_max_proto_version(wctx->ssl_ctx, TLS1_VERSION); + *max_version = TLS1_VERSION; break; case CURL_SSLVERSION_MAX_DEFAULT: case CURL_SSLVERSION_MAX_NONE: - res = WOLFSSL_SUCCESS; break; default: failf(data, "wolfSSL: unsupported maximum TLS version value"); return CURLE_SSL_CONNECT_ERROR; } + + res = wolfSSL_CTX_set_min_proto_version(wctx->ssl_ctx, *min_version); if(res != WOLFSSL_SUCCESS) { - failf(data, "wolfSSL: failed set the maximum TLS version"); + failf(data, "wolfSSL: failed set the minimum TLS version"); return CURLE_SSL_CONNECT_ERROR; } + + if(*max_version) { + res = wolfSSL_CTX_set_max_proto_version(wctx->ssl_ctx, *max_version); + if(res != WOLFSSL_SUCCESS) { + failf(data, "wolfSSL: failed set the maximum TLS version"); + return CURLE_SSL_CONNECT_ERROR; + } + } return CURLE_OK; } - #define QUIC_GROUPS "P-256:P-384:P-521" CURLcode Curl_wssl_ctx_init(struct wssl_ctx *wctx, @@ -1111,7 +1108,7 @@ CURLcode Curl_wssl_ctx_init(struct wssl_ctx *wctx, { struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); struct ssl_primary_config *conn_config; - WOLFSSL_METHOD* req_method = NULL; + WOLFSSL_METHOD *req_method = NULL; struct alpn_spec alpns; char *curves; #ifdef WOLFSSL_HAVE_KYBER @@ -1120,6 +1117,7 @@ CURLcode Curl_wssl_ctx_init(struct wssl_ctx *wctx, #endif CURLcode result = CURLE_FAILED_INIT; unsigned char transport; + int tls_min, tls_max; DEBUGASSERT(!wctx->ssl_ctx); DEBUGASSERT(!wctx->ssl); @@ -1153,7 +1151,7 @@ CURLcode Curl_wssl_ctx_init(struct wssl_ctx *wctx, goto out; } - result = ssl_version(data, conn_config, wctx); + result = ssl_version(data, conn_config, wctx, &tls_min, &tls_max); if(result) goto out; @@ -1177,12 +1175,14 @@ CURLcode Curl_wssl_ctx_init(struct wssl_ctx *wctx, struct dynbuf c; curlx_dyn_init(&c, MAX_CIPHER_LEN); - if(ciphers13) - result = curlx_dyn_add(&c, ciphers13); - else - result = wssl_add_default_ciphers(TRUE, &c); + if(!tls_max || (tls_max >= TLS1_3_VERSION)) { + if(ciphers13) + result = curlx_dyn_add(&c, ciphers13); + else + result = wssl_add_default_ciphers(TRUE, &c); + } - if(!result) { + if(!result && (tls_min < TLS1_3_VERSION)) { if(ciphers12) { if(curlx_dyn_len(&c)) result = curlx_dyn_addn(&c, ":", 1); @@ -1257,10 +1257,12 @@ CURLcode Curl_wssl_ctx_init(struct wssl_ctx *wctx, } #endif - if(ssl_config->primary.cache_session && (transport != TRNSPRT_QUIC)) { +#ifdef HAVE_EX_DATA + if(Curl_ssl_scache_use(cf, data) && (transport != TRNSPRT_QUIC)) { /* Register to get notified when a new session is received */ wolfSSL_CTX_sess_set_new_cb(wctx->ssl_ctx, wssl_vtls_new_session_cb); } +#endif if(cb_setup) { result = cb_setup(cf, data, cb_user_data); @@ -1301,7 +1303,11 @@ CURLcode Curl_wssl_ctx_init(struct wssl_ctx *wctx, goto out; } +#ifdef HAVE_EX_DATA wolfSSL_set_app_data(wctx->ssl, ssl_user_data); +#else + (void)ssl_user_data; +#endif #ifdef WOLFSSL_QUIC if(transport == TRNSPRT_QUIC) wolfSSL_set_quic_use_legacy_codepoint(wctx->ssl, 0); @@ -1316,7 +1322,7 @@ CURLcode Curl_wssl_ctx_init(struct wssl_ctx *wctx, #endif /* Check if there is a cached ID we can/should use here! */ - if(ssl_config->primary.cache_session) { + if(Curl_ssl_scache_use(cf, data)) { /* Set session from cache if there is one */ (void)wssl_setup_session(cf, data, wctx, &alpns, peer->scache_key, sess_reuse_cb); @@ -1344,8 +1350,7 @@ CURLcode Curl_wssl_ctx_init(struct wssl_ctx *wctx, /* Ensure the Client Random is preserved. */ wolfSSL_KeepArrays(wctx->ssl); #if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13) - wolfSSL_set_tls13_secret_cb(wctx->ssl, - wssl_tls13_secret_callback, NULL); + wolfSSL_set_tls13_secret_cb(wctx->ssl, wssl_tls13_secret_callback, NULL); #endif } #endif /* OPENSSL_EXTRA */ @@ -1358,7 +1363,7 @@ CURLcode Curl_wssl_ctx_init(struct wssl_ctx *wctx, } #endif /* HAVE_SECURE_RENEGOTIATION */ -#ifdef USE_ECH_WOLFSSL +#ifdef HAVE_WOLFSSL_CTX_GENERATEECHCONFIG if(ECH_ENABLED(data)) { int trying_ech_now = 0; @@ -1370,23 +1375,23 @@ CURLcode Curl_wssl_ctx_init(struct wssl_ctx *wctx, if(data->set.tls_ech == CURLECH_GREASE) { infof(data, "ECH: GREASE is done by default by wolfSSL: no need to ask"); } - if(data->set.tls_ech & CURLECH_CLA_CFG - && data->set.str[STRING_ECH_CONFIG]) { + if(data->set.tls_ech & CURLECH_CLA_CFG && + data->set.str[STRING_ECH_CONFIG]) { char *b64val = data->set.str[STRING_ECH_CONFIG]; word32 b64len = 0; - b64len = (word32) strlen(b64val); - if(b64len - && wolfSSL_SetEchConfigsBase64(wctx->ssl, b64val, b64len) - != WOLFSSL_SUCCESS) { + b64len = (word32)strlen(b64val); + if(b64len && + wolfSSL_SetEchConfigsBase64(wctx->ssl, + b64val, b64len) != WOLFSSL_SUCCESS) { if(data->set.tls_ech & CURLECH_HARD) { result = CURLE_SSL_CONNECT_ERROR; goto out; } } else { - trying_ech_now = 1; - infof(data, "ECH: ECHConfig from command line"); + trying_ech_now = 1; + infof(data, "ECH: ECHConfig from command line"); } } else { @@ -1411,8 +1416,8 @@ CURLcode Curl_wssl_ctx_init(struct wssl_ctx *wctx, size_t elen = rinfo->echconfiglist_len; infof(data, "ECH: ECHConfig from DoH HTTPS RR"); - if(wolfSSL_SetEchConfigs(wctx->ssl, ecl, (word32) elen) != - WOLFSSL_SUCCESS) { + if(wolfSSL_SetEchConfigs(wctx->ssl, ecl, (word32)elen) != + WOLFSSL_SUCCESS) { infof(data, "ECH: wolfSSL_SetEchConfigs failed"); if(data->set.tls_ech & CURLECH_HARD) { result = CURLE_SSL_CONNECT_ERROR; @@ -1443,7 +1448,7 @@ CURLcode Curl_wssl_ctx_init(struct wssl_ctx *wctx, } } -#endif /* USE_ECH_WOLFSSL */ +#endif /* HAVE_WOLFSSL_CTX_GENERATEECHCONFIG */ result = CURLE_OK; @@ -1463,8 +1468,8 @@ CURLcode Curl_wssl_ctx_init(struct wssl_ctx *wctx, * This function loads all the client/CA certificates and CRLs. Setup the TLS * layer and do all necessary magic. */ -static CURLcode -wssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) +static CURLcode wssl_connect_step1(struct Curl_cfilter *cf, + struct Curl_easy *data) { struct ssl_connect_data *connssl = cf->ctx; struct wssl_ctx *wssl = (struct wssl_ctx *)connssl->backend; @@ -1491,11 +1496,10 @@ wssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) } #endif - /* Enable RFC2818 checks */ - if(conn_config->verifyhost) { - char *snihost = connssl->peer.sni ? - connssl->peer.sni : connssl->peer.hostname; - if(wolfSSL_check_domain_name(wssl->ssl, snihost) != + /* Enable RFC2818 checks on domain names. This cannot check + * IP addresses which we need to do extra after the handshake. */ + if(conn_config->verifyhost && connssl->peer.sni) { + if(wolfSSL_check_domain_name(wssl->ssl, connssl->peer.sni) != WOLFSSL_SUCCESS) { return CURLE_SSL_CONNECT_ERROR; } @@ -1505,6 +1509,8 @@ wssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) { WOLFSSL_BIO *bio; + if(!wssl_bio_cf_method) + return CURLE_FAILED_INIT; bio = wolfSSL_BIO_new(wssl_bio_cf_method); if(!bio) return CURLE_OUT_OF_MEMORY; @@ -1512,21 +1518,23 @@ wssl_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) wolfSSL_BIO_set_data(bio, cf); wolfSSL_set_bio(wssl->ssl, bio, bio); } -#else /* USE_BIO_CHAIN */ +#else /* !USE_BIO_CHAIN */ + curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data); + if(sockfd > INT_MAX) { + failf(data, "SSL: socket value too large"); + return CURLE_SSL_CONNECT_ERROR; + } /* pass the raw socket into the SSL layer */ - if(!wolfSSL_set_fd(wssl->ssl, - (int)Curl_conn_cf_get_socket(cf, data))) { + if(!wolfSSL_set_fd(wssl->ssl, (int)sockfd)) { failf(data, "SSL: wolfSSL_set_fd failed"); return CURLE_SSL_CONNECT_ERROR; } -#endif /* !USE_BIO_CHAIN */ +#endif /* USE_BIO_CHAIN */ return CURLE_OK; } - -static char *wssl_strerror(unsigned long error, char *buf, - unsigned long size) +static char *wssl_strerror(unsigned long error, char *buf, unsigned long size) { DEBUGASSERT(size > 40); *buf = '\0'; @@ -1535,8 +1543,7 @@ static char *wssl_strerror(unsigned long error, char *buf, if(!*buf) { const char *msg = error ? "Unknown error" : "No error"; - /* the string fits because the assert above assures this */ - strcpy(buf, msg); + curlx_strcopy(buf, size, msg, strlen(msg)); } return buf; @@ -1546,6 +1553,8 @@ CURLcode Curl_wssl_verify_pinned(struct Curl_cfilter *cf, struct Curl_easy *data, struct wssl_ctx *wssl) { + WOLFSSL_X509 *x509 = NULL; + CURLcode result = CURLE_OK; #ifndef CURL_DISABLE_PROXY const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf) ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : @@ -1557,50 +1566,48 @@ CURLcode Curl_wssl_verify_pinned(struct Curl_cfilter *cf, if(pinnedpubkey) { #ifdef KEEP_PEER_CERT - WOLFSSL_X509 *x509; const char *x509_der; int x509_der_len; struct Curl_X509certificate x509_parsed; struct Curl_asn1Element *pubkey; - CURLcode result; + + result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; x509 = wolfSSL_get_peer_certificate(wssl->ssl); if(!x509) { failf(data, "SSL: failed retrieving server certificate"); - return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + goto end; } x509_der = (const char *)wolfSSL_X509_get_der(x509, &x509_der_len); if(!x509_der) { failf(data, "SSL: failed retrieving ASN.1 server certificate"); - return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + goto end; } memset(&x509_parsed, 0, sizeof(x509_parsed)); if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len)) - return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + goto end; pubkey = &x509_parsed.subjectPublicKeyInfo; if(!pubkey->header || pubkey->end <= pubkey->header) { failf(data, "SSL: failed retrieving public key from server certificate"); - return CURLE_SSL_PINNEDPUBKEYNOTMATCH; + goto end; } - result = Curl_pin_peer_pubkey(data, - pinnedpubkey, + result = Curl_pin_peer_pubkey(data, pinnedpubkey, (const unsigned char *)pubkey->header, (size_t)(pubkey->end - pubkey->header)); - wolfSSL_FreeX509(x509); - if(result) { + if(result) failf(data, "SSL: public key does not match pinned public key"); - return result; - } #else failf(data, "Library lacks pinning support built-in"); return CURLE_NOT_BUILT_IN; #endif } - return CURLE_OK; +end: + wolfSSL_FreeX509(x509); + return result; } #ifdef WOLFSSL_EARLY_DATA @@ -1609,7 +1616,6 @@ static CURLcode wssl_send_earlydata(struct Curl_cfilter *cf, { struct ssl_connect_data *connssl = cf->ctx; struct wssl_ctx *wssl = (struct wssl_ctx *)connssl->backend; - CURLcode result = CURLE_OK; const unsigned char *buf; size_t blen; @@ -1624,23 +1630,17 @@ static CURLcode wssl_send_earlydata(struct Curl_cfilter *cf, blen, rc, nwritten); if(rc < 0) { int err = wolfSSL_get_error(wssl->ssl, rc); + char error_buffer[256]; switch(err) { case WOLFSSL_ERROR_NONE: /* just did not get anything */ case WOLFSSL_ERROR_WANT_READ: case WOLFSSL_ERROR_WANT_WRITE: - result = CURLE_AGAIN; - break; - default: { - char error_buffer[256]; - CURL_TRC_CF(data, cf, "SSL send early data, error: '%s'(%d)", - wssl_strerror((unsigned long)err, error_buffer, - sizeof(error_buffer)), - err); - result = CURLE_SEND_ERROR; - break; - } + return CURLE_AGAIN; } - goto out; + CURL_TRC_CF(data, cf, "SSL send early data, error: '%s'(%d)", + wssl_strerror((unsigned long)err, error_buffer, + sizeof(error_buffer)), err); + return CURLE_SEND_ERROR; } Curl_bufq_skip(&connssl->earlydata, (size_t)nwritten); @@ -1650,13 +1650,11 @@ static CURLcode wssl_send_earlydata(struct Curl_cfilter *cf, if(!Curl_ssl_cf_is_proxy(cf)) Curl_pgrsEarlyData(data, (curl_off_t)connssl->earlydata_skip); infof(data, "SSL sending %zu bytes of early data", connssl->earlydata_skip); -out: - return result; + return CURLE_OK; } #endif /* WOLFSSL_EARLY_DATA */ -static CURLcode wssl_handshake(struct Curl_cfilter *cf, - struct Curl_easy *data) +static CURLcode wssl_handshake(struct Curl_cfilter *cf, struct Curl_easy *data) { struct ssl_connect_data *connssl = cf->ctx; struct wssl_ctx *wssl = (struct wssl_ctx *)connssl->backend; @@ -1719,6 +1717,25 @@ static CURLcode wssl_handshake(struct Curl_cfilter *cf, detail = wolfSSL_get_error(wssl->ssl, ret); CURL_TRC_CF(data, cf, "wolfSSL_connect() -> %d, detail=%d", ret, detail); + /* On a successful handshake with an IP address, do an extra check + * on the peer certificate */ + if(ret == WOLFSSL_SUCCESS && + conn_config->verifyhost && + !connssl->peer.sni) { + /* we have an IP address as hostname. */ + WOLFSSL_X509 *cert = wolfSSL_get_peer_certificate(wssl->ssl); + if(!cert) { + failf(data, "unable to get peer certificate"); + return CURLE_PEER_FAILED_VERIFICATION; + } + ret = wolfSSL_X509_check_ip_asc(cert, connssl->peer.hostname, 0); + CURL_TRC_CF(data, cf, "check peer certificate for IP match on %s -> %d", + connssl->peer.hostname, ret); + if(ret != WOLFSSL_SUCCESS) + detail = DOMAIN_NAME_MISMATCH; + wolfSSL_X509_free(cert); + } + if(ret == WOLFSSL_SUCCESS) { return CURLE_OK; } @@ -1760,14 +1777,14 @@ static CURLcode wssl_handshake(struct Curl_cfilter *cf, } else if(wssl->io_result) { switch(wssl->io_result) { - case CURLE_SEND_ERROR: - case CURLE_RECV_ERROR: - return CURLE_SSL_CONNECT_ERROR; - default: - return wssl->io_result; + case CURLE_SEND_ERROR: + case CURLE_RECV_ERROR: + return CURLE_SSL_CONNECT_ERROR; + default: + return wssl->io_result; } } -#ifdef USE_ECH_WOLFSSL +#ifdef HAVE_WOLFSSL_CTX_GENERATEECHCONFIG else if(detail == -1) { /* try access a retry_config ECHConfigList for tracing */ byte echConfigs[1000]; @@ -1775,8 +1792,7 @@ static CURLcode wssl_handshake(struct Curl_cfilter *cf, int rv = 0; /* this currently does not produce the retry_configs */ - rv = wolfSSL_GetEchConfigs(wssl->ssl, echConfigs, - &echConfigsLen); + rv = wolfSSL_GetEchConfigs(wssl->ssl, echConfigs, &echConfigsLen); if(rv != WOLFSSL_SUCCESS) { infof(data, "Failed to get ECHConfigs"); } @@ -1784,11 +1800,11 @@ static CURLcode wssl_handshake(struct Curl_cfilter *cf, char *b64str = NULL; size_t blen = 0; - result = curlx_base64_encode((const char *)echConfigs, echConfigsLen, + result = curlx_base64_encode(echConfigs, echConfigsLen, &b64str, &blen); if(!result && b64str) infof(data, "ECH: (not yet) retry_configs %s", b64str); - free(b64str); + curlx_free(b64str); } return CURLE_SSL_CONNECT_ERROR; } @@ -2058,7 +2074,6 @@ size_t Curl_wssl_version(char *buffer, size_t size) #endif } - static int wssl_init(void) { int ret; @@ -2067,11 +2082,11 @@ static int wssl_init(void) Curl_tls_keylog_open(); #endif ret = (wolfSSL_Init() == WOLFSSL_SUCCESS); - wssl_bio_cf_init_methods(); + if(ret) + ret = wssl_bio_cf_init_methods(); return ret; } - static void wssl_cleanup(void) { wssl_bio_cf_free_methods(); @@ -2081,7 +2096,6 @@ static void wssl_cleanup(void) #endif } - static bool wssl_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data) { @@ -2098,15 +2112,14 @@ static bool wssl_data_pending(struct Curl_cfilter *cf, return FALSE; } -void Curl_wssl_report_handshake(struct Curl_easy *data, - struct wssl_ctx *wssl) +void Curl_wssl_report_handshake(struct Curl_easy *data, struct wssl_ctx *wssl) { #if (LIBWOLFSSL_VERSION_HEX >= 0x03009010) - infof(data, "SSL connection using %s / %s", - wolfSSL_get_version(wssl->ssl), - wolfSSL_get_cipher_name(wssl->ssl)); + infof(data, "SSL connection using %s / %s", + wolfSSL_get_version(wssl->ssl), + wolfSSL_get_cipher_name(wssl->ssl)); #else - infof(data, "SSL connected"); + infof(data, "SSL connected"); #endif } @@ -2267,7 +2280,7 @@ const struct Curl_ssl Curl_ssl_wolfssl = { #endif SSLSUPP_CA_PATH | SSLSUPP_CAINFO_BLOB | -#ifdef USE_ECH_WOLFSSL +#ifdef HAVE_WOLFSSL_CTX_GENERATEECHCONFIG SSLSUPP_ECH | #endif SSLSUPP_SSL_CTX | diff --git a/lib/vtls/wolfssl.h b/lib/vtls/wolfssl.h index 7ff4cfb88178..736da9a1a6a2 100644 --- a/lib/vtls/wolfssl.h +++ b/lib/vtls/wolfssl.h @@ -41,9 +41,9 @@ extern const struct Curl_ssl Curl_ssl_wolfssl; struct wssl_ctx { struct WOLFSSL_CTX *ssl_ctx; - struct WOLFSSL *ssl; - CURLcode io_result; /* result of last BIO cfilter operation */ - CURLcode hs_result; /* result of handshake */ + struct WOLFSSL *ssl; + CURLcode io_result; /* result of last BIO cfilter operation */ + CURLcode hs_result; /* result of handshake */ int io_send_blocked_len; /* length of last BIO write that EAGAIN-ed */ BIT(x509_store_setup); /* x509 store has been set up */ BIT(shutting_down); /* TLS is being shut down */ @@ -75,6 +75,7 @@ CURLcode Curl_wssl_setup_x509_store(struct Curl_cfilter *cf, struct Curl_easy *data, struct wssl_ctx *wssl); +#ifdef HAVE_EX_DATA CURLcode Curl_wssl_cache_session(struct Curl_cfilter *cf, struct Curl_easy *data, const char *ssl_peer_key, @@ -83,13 +84,13 @@ CURLcode Curl_wssl_cache_session(struct Curl_cfilter *cf, const char *alpn, unsigned char *quic_tp, size_t quic_tp_len); +#endif CURLcode Curl_wssl_verify_pinned(struct Curl_cfilter *cf, struct Curl_easy *data, struct wssl_ctx *wssl); -void Curl_wssl_report_handshake(struct Curl_easy *data, - struct wssl_ctx *wssl); +void Curl_wssl_report_handshake(struct Curl_easy *data, struct wssl_ctx *wssl); #endif /* USE_WOLFSSL */ #endif /* HEADER_CURL_WOLFSSL_H */ diff --git a/lib/vtls/x509asn1.c b/lib/vtls/x509asn1.c index c5fc86351524..e23331e9d676 100644 --- a/lib/vtls/x509asn1.c +++ b/lib/vtls/x509asn1.c @@ -37,28 +37,19 @@ #define WANT_EXTRACT_CERTINFO /* uses Curl_extract_certinfo() */ #endif -#include #include "../urldata.h" -#include "../curl_ctype.h" -#include "hostcheck.h" #include "vtls.h" -#include "vtls_int.h" -#include "../sendf.h" -#include "../curlx/inet_pton.h" +#include "../curl_trc.h" #include "../curlx/base64.h" #include "x509asn1.h" #include "../curlx/dynbuf.h" -/* The last 2 #include files should be in this order */ -#include "../curl_memory.h" -#include "../memdebug.h" - /* * Constants. */ /* Largest supported ASN.1 structure. */ -#define CURL_ASN1_MAX ((size_t) 0x40000) /* 256K */ +#define CURL_ASN1_MAX ((size_t)0x40000) /* 256K */ /* ASN.1 classes. */ /* #define CURL_ASN1_UNIVERSAL 0 */ @@ -96,7 +87,6 @@ /* #define CURL_ASN1_CHARACTER_STRING 29 */ #define CURL_ASN1_BMP_STRING 30 - #ifdef WANT_EXTRACT_CERTINFO /* ASN.1 OID table entry. */ struct Curl_OID { @@ -157,7 +147,7 @@ static const struct Curl_OID OIDtable[] = { { "2.16.840.1.101.3.4.2.2", "sha384" }, { "2.16.840.1.101.3.4.2.3", "sha512" }, { "1.2.840.113549.1.9.2", "unstructuredName" }, - { (const char *) NULL, (const char *) NULL } + { (const char *)NULL, (const char *)NULL } }; #endif /* WANT_EXTRACT_CERTINFO */ @@ -191,12 +181,12 @@ static const char *getASN1Element_(struct Curl_asn1Element *elem, if an error occurs. */ if(!beg || !end || beg >= end || !*beg || ((size_t)(end - beg) > CURL_ASN1_MAX) || - lvl >= CURL_ASN1_MAX_RECURSIONS) + lvl >= CURL_ASN1_MAX_RECURSIONS) return NULL; /* Process header byte. */ elem->header = beg; - b = (unsigned char) *beg++; + b = (unsigned char)*beg++; elem->constructed = (b & 0x20) != 0; elem->eclass = (b >> 6) & 3; b &= 0x1F; @@ -207,7 +197,7 @@ static const char *getASN1Element_(struct Curl_asn1Element *elem, /* Process length. */ if(beg >= end) return NULL; - b = (unsigned char) *beg++; + b = (unsigned char)*beg++; if(!(b & 0x80)) len = b; else if(!(b &= 0x7F)) { @@ -288,7 +278,7 @@ static CURLcode bool2str(struct dynbuf *store, { if(end - beg != 1) return CURLE_BAD_FUNCTION_ARGUMENT; - return curlx_dyn_add(store, *beg ? "TRUE": "FALSE"); + return curlx_dyn_add(store, *beg ? "TRUE" : "FALSE"); } /* @@ -302,13 +292,12 @@ static CURLcode octet2str(struct dynbuf *store, CURLcode result = CURLE_OK; while(!result && beg < end) - result = curlx_dyn_addf(store, "%02x:", (unsigned char) *beg++); + result = curlx_dyn_addf(store, "%02x:", (unsigned char)*beg++); return result; } -static CURLcode bit2str(struct dynbuf *store, - 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. */ @@ -322,8 +311,7 @@ static CURLcode bit2str(struct dynbuf *store, * * Returns error. */ -static CURLcode int2str(struct dynbuf *store, - 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; @@ -339,7 +327,7 @@ static CURLcode int2str(struct dynbuf *store, val = ~val; do - val = (val << 8) | *(const unsigned char *) beg++; + val = (val << 8) | *(const unsigned char *)beg++; while(beg < end); return curlx_dyn_addf(store, "%s%x", val >= 10 ? "0x" : "", val); } @@ -352,8 +340,8 @@ static CURLcode int2str(struct dynbuf *store, * * Returns error. */ -static CURLcode -utf8asn1str(struct dynbuf *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; @@ -394,14 +382,14 @@ utf8asn1str(struct dynbuf *to, int type, const char *from, const char *end) switch(size) { case 4: - wc = (wc << 8) | *(const unsigned char *) from++; - wc = (wc << 8) | *(const unsigned char *) from++; + wc = (wc << 8) | *(const unsigned char *)from++; + wc = (wc << 8) | *(const unsigned char *)from++; FALLTHROUGH(); case 2: - wc = (wc << 8) | *(const unsigned char *) from++; + wc = (wc << 8) | *(const unsigned char *)from++; FALLTHROUGH(); default: /* case 1: */ - wc = (wc << 8) | *(const unsigned char *) from++; + wc = (wc << 8) | *(const unsigned char *)from++; } if(wc >= 0x00000080) { if(wc >= 0x00000800) { @@ -410,19 +398,19 @@ utf8asn1str(struct dynbuf *to, int type, const char *from, const char *end) /* Invalid char. size for target encoding. */ return CURLE_WEIRD_SERVER_REPLY; } - buf[3] = (char) (0x80 | (wc & 0x3F)); + buf[3] = (char)(0x80 | (wc & 0x3F)); wc = (wc >> 6) | 0x00010000; charsize++; } - buf[2] = (char) (0x80 | (wc & 0x3F)); + buf[2] = (char)(0x80 | (wc & 0x3F)); wc = (wc >> 6) | 0x00000800; charsize++; } - buf[1] = (char) (0x80 | (wc & 0x3F)); + buf[1] = (char)(0x80 | (wc & 0x3F)); wc = (wc >> 6) | 0x000000C0; charsize++; } - buf[0] = (char) wc; + buf[0] = (char)wc; result = curlx_dyn_addn(to, buf, charsize); } } @@ -442,7 +430,7 @@ static CURLcode encodeOID(struct dynbuf *store, CURLcode result = CURLE_OK; /* Process the first two numbers. */ - y = *(const unsigned char *) beg++; + y = *(const unsigned char *)beg++; x = y / 40; y -= x * 40; @@ -456,7 +444,7 @@ static CURLcode encodeOID(struct dynbuf *store, do { if(x & 0xFF000000) return CURLE_OK; - y = *(const unsigned char *) beg++; + y = *(const unsigned char *)beg++; x = (x << 7) | (y & 0x7F); } while(y & 0x80); result = curlx_dyn_addf(store, ".%u", x); @@ -977,8 +965,8 @@ static CURLcode do_pubkey_field(struct Curl_easy *data, int certnum, } /* return 0 on success, 1 on error */ -static int do_pubkey(struct Curl_easy *data, int certnum, - const char *algo, struct Curl_asn1Element *param, +static int do_pubkey(struct Curl_easy *data, int certnum, const char *algo, + struct Curl_asn1Element *param, struct Curl_asn1Element *pubkey) { struct Curl_asn1Element elem; @@ -1023,7 +1011,7 @@ static int do_pubkey(struct Curl_easy *data, int certnum, len = ((elem.end - q) * 8); if(len) { unsigned int i; - for(i = *(const unsigned char *) q; !(i & 0x80); i <<= 1) + for(i = *(const unsigned char *)q; !(i & 0x80); i <<= 1) len--; } if(len > 32) @@ -1082,8 +1070,7 @@ static int do_pubkey(struct Curl_easy *data, int certnum, * Convert an ASN.1 distinguished name into a printable string. * Return error. */ -static CURLcode DNtostr(struct dynbuf *store, - struct Curl_asn1Element *dn) +static CURLcode DNtostr(struct dynbuf *store, struct Curl_asn1Element *dn) { return encodeDN(store, dn); } @@ -1139,7 +1126,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, /* Version (always fits in less than 32 bits). */ version = 0; for(ptr = cert.version.beg; ptr < cert.version.end; ptr++) - version = (version << 8) | *(const unsigned char *) ptr; + version = (version << 8) | *(const unsigned char *)ptr; if(data->set.ssl.certinfo) { result = curlx_dyn_addf(&out, "%x", version); if(result) @@ -1167,8 +1154,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, if(result) goto done; if(data->set.ssl.certinfo) { - result = ssl_push_certinfo_dyn(data, certnum, "Signature Algorithm", - &out); + result = ssl_push_certinfo_dyn(data, certnum, "Signature Algorithm", &out); if(result) goto done; } @@ -1228,7 +1214,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, curlx_dyn_reset(&out); /* Generate PEM certificate. */ - result = curlx_base64_encode(cert.certificate.beg, + result = curlx_base64_encode((const uint8_t *)cert.certificate.beg, cert.certificate.end - cert.certificate.beg, &certptr, &clen); if(result) @@ -1260,7 +1246,7 @@ CURLcode Curl_extract_certinfo(struct Curl_easy *data, if(!result) result = curlx_dyn_add(&out, "-----END CERTIFICATE-----\n"); } - free(certptr); + curlx_free(certptr); if(!result) if(data->set.ssl.certinfo) result = ssl_push_certinfo_dyn(data, certnum, "Cert", &out); diff --git a/lib/ws.c b/lib/ws.c index ec7923555030..0f60d4421369 100644 --- a/lib/ws.c +++ b/lib/ws.c @@ -22,7 +22,6 @@ * ***************************************************************************/ #include "curl_setup.h" -#include #if !defined(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP) @@ -34,18 +33,14 @@ #include "curlx/base64.h" #include "connect.h" #include "sendf.h" +#include "curl_trc.h" #include "multiif.h" #include "ws.h" #include "easyif.h" #include "transfer.h" #include "select.h" -#include "curlx/nonblock.h" #include "curlx/strparse.h" - -/* The last 2 #include files should be in this order */ -#include "curl_memory.h" -#include "memdebug.h" - +#include "curlx/strcopy.h" /*** RFC 6455 Section 5.2 @@ -57,11 +52,11 @@ |N|V|V|V| | | |1|2|3| | */ -#define WSBIT_FIN (0x80) -#define WSBIT_RSV1 (0x40) -#define WSBIT_RSV2 (0x20) -#define WSBIT_RSV3 (0x10) -#define WSBIT_RSV_MASK (WSBIT_RSV1 | WSBIT_RSV2 | WSBIT_RSV3) +#define WSBIT_FIN (0x80) +#define WSBIT_RSV1 (0x40) +#define WSBIT_RSV2 (0x20) +#define WSBIT_RSV3 (0x10) +#define WSBIT_RSV_MASK (WSBIT_RSV1 | WSBIT_RSV2 | WSBIT_RSV3) #define WSBIT_OPCODE_CONT (0x0) #define WSBIT_OPCODE_TEXT (0x1) #define WSBIT_OPCODE_BIN (0x2) @@ -73,10 +68,9 @@ #define WSBIT_MASK 0x80 /* buffer dimensioning */ -#define WS_CHUNK_SIZE 65535 +#define WS_CHUNK_SIZE 65535 #define WS_CHUNK_COUNT 2 - /* a client-side WS frame decoder, parsing frame headers and * payload, keeping track of current position and stats */ enum ws_dec_state { @@ -90,7 +84,7 @@ struct ws_decoder { int frame_flags; /* See the CURLWS_* defines */ curl_off_t payload_offset; /* the offset parsing is at */ curl_off_t payload_len; - unsigned char head[10]; + uint8_t head[10]; int head_len, head_total; enum ws_dec_state state; int cont_flags; @@ -102,8 +96,8 @@ struct ws_encoder { curl_off_t payload_len; /* payload length of current frame */ curl_off_t payload_remain; /* remaining payload of current */ unsigned int xori; /* xor index */ - unsigned char mask[4]; /* 32-bit mask for this connection */ - unsigned char firstbyte; /* first byte of frame we encode */ + uint8_t mask[4]; /* 32-bit mask for this connection */ + uint8_t firstbyte; /* first byte of frame we encode */ BIT(contfragment); /* set TRUE if the previous fragment sent was not final */ }; @@ -113,7 +107,7 @@ struct ws_encoder { struct ws_cntrl_frame { unsigned int type; size_t payload_len; - unsigned char payload[WS_MAX_CNTRL_LEN]; + uint8_t payload[WS_MAX_CNTRL_LEN]; }; /* A websocket connection with en- and decoder that treat frames @@ -129,166 +123,165 @@ struct websocket { size_t sendbuf_payload; /* number of payload bytes in sendbuf */ }; - -static const char *ws_frame_name_of_op(unsigned char firstbyte) +static const char *ws_frame_name_of_op(uint8_t firstbyte) { switch(firstbyte & WSBIT_OPCODE_MASK) { - case WSBIT_OPCODE_CONT: - return "CONT"; - case WSBIT_OPCODE_TEXT: - return "TEXT"; - case WSBIT_OPCODE_BIN: - return "BIN"; - case WSBIT_OPCODE_CLOSE: - return "CLOSE"; - case WSBIT_OPCODE_PING: - return "PING"; - case WSBIT_OPCODE_PONG: - return "PONG"; - default: - return "???"; + case WSBIT_OPCODE_CONT: + return "CONT"; + case WSBIT_OPCODE_TEXT: + return "TEXT"; + case WSBIT_OPCODE_BIN: + return "BIN"; + case WSBIT_OPCODE_CLOSE: + return "CLOSE"; + case WSBIT_OPCODE_PING: + return "PING"; + case WSBIT_OPCODE_PONG: + return "PONG"; + default: + return "???"; } } static int ws_frame_firstbyte2flags(struct Curl_easy *data, - unsigned char firstbyte, int cont_flags) + uint8_t firstbyte, int cont_flags) { switch(firstbyte) { - /* 0x00 - intermediate TEXT/BINARY fragment */ - case WSBIT_OPCODE_CONT: - if(!(cont_flags & CURLWS_CONT)) { - failf(data, "[WS] no ongoing fragmented message to resume"); - return 0; - } - return cont_flags | CURLWS_CONT; - /* 0x80 - final TEXT/BIN fragment */ - case (WSBIT_OPCODE_CONT | WSBIT_FIN): - if(!(cont_flags & CURLWS_CONT)) { - failf(data, "[WS] no ongoing fragmented message to resume"); - return 0; - } - return cont_flags & ~CURLWS_CONT; - /* 0x01 - first TEXT fragment */ - case WSBIT_OPCODE_TEXT: - if(cont_flags & CURLWS_CONT) { - failf(data, "[WS] fragmented message interrupted by new TEXT msg"); - return 0; - } - return CURLWS_TEXT | CURLWS_CONT; - /* 0x81 - unfragmented TEXT msg */ - case (WSBIT_OPCODE_TEXT | WSBIT_FIN): - if(cont_flags & CURLWS_CONT) { - failf(data, "[WS] fragmented message interrupted by new TEXT msg"); - return 0; - } - return CURLWS_TEXT; - /* 0x02 - first BINARY fragment */ - case WSBIT_OPCODE_BIN: - if(cont_flags & CURLWS_CONT) { - failf(data, "[WS] fragmented message interrupted by new BINARY msg"); - return 0; - } - return CURLWS_BINARY | CURLWS_CONT; - /* 0x82 - unfragmented BINARY msg */ - case (WSBIT_OPCODE_BIN | WSBIT_FIN): - if(cont_flags & CURLWS_CONT) { - failf(data, "[WS] fragmented message interrupted by new BINARY msg"); - return 0; - } - return CURLWS_BINARY; - /* 0x08 - first CLOSE fragment */ - case WSBIT_OPCODE_CLOSE: - failf(data, "[WS] invalid fragmented CLOSE frame"); + /* 0x00 - intermediate TEXT/BINARY fragment */ + case WSBIT_OPCODE_CONT: + if(!(cont_flags & CURLWS_CONT)) { + failf(data, "[WS] no ongoing fragmented message to resume"); return 0; - /* 0x88 - unfragmented CLOSE */ - case (WSBIT_OPCODE_CLOSE | WSBIT_FIN): - return CURLWS_CLOSE; - /* 0x09 - first PING fragment */ - case WSBIT_OPCODE_PING: - failf(data, "[WS] invalid fragmented PING frame"); + } + return cont_flags | CURLWS_CONT; + /* 0x80 - final TEXT/BIN fragment */ + case (WSBIT_OPCODE_CONT | WSBIT_FIN): + if(!(cont_flags & CURLWS_CONT)) { + failf(data, "[WS] no ongoing fragmented message to resume"); return 0; - /* 0x89 - unfragmented PING */ - case (WSBIT_OPCODE_PING | WSBIT_FIN): - return CURLWS_PING; - /* 0x0a - first PONG fragment */ - case WSBIT_OPCODE_PONG: - failf(data, "[WS] invalid fragmented PONG frame"); + } + return cont_flags & ~CURLWS_CONT; + /* 0x01 - first TEXT fragment */ + case WSBIT_OPCODE_TEXT: + if(cont_flags & CURLWS_CONT) { + failf(data, "[WS] fragmented message interrupted by new TEXT msg"); return 0; - /* 0x8a - unfragmented PONG */ - case (WSBIT_OPCODE_PONG | WSBIT_FIN): - return CURLWS_PONG; - /* invalid first byte */ - default: - if(firstbyte & WSBIT_RSV_MASK) - /* any of the reserved bits 0x40/0x20/0x10 are set */ - failf(data, "[WS] invalid reserved bits: %02x", firstbyte); - else - /* any of the reserved opcodes 0x3-0x7 or 0xb-0xf is used */ - failf(data, "[WS] invalid opcode: %02x", firstbyte); + } + return CURLWS_TEXT | CURLWS_CONT; + /* 0x81 - unfragmented TEXT msg */ + case (WSBIT_OPCODE_TEXT | WSBIT_FIN): + if(cont_flags & CURLWS_CONT) { + failf(data, "[WS] fragmented message interrupted by new TEXT msg"); return 0; + } + return CURLWS_TEXT; + /* 0x02 - first BINARY fragment */ + case WSBIT_OPCODE_BIN: + if(cont_flags & CURLWS_CONT) { + failf(data, "[WS] fragmented message interrupted by new BINARY msg"); + return 0; + } + return CURLWS_BINARY | CURLWS_CONT; + /* 0x82 - unfragmented BINARY msg */ + case (WSBIT_OPCODE_BIN | WSBIT_FIN): + if(cont_flags & CURLWS_CONT) { + failf(data, "[WS] fragmented message interrupted by new BINARY msg"); + return 0; + } + return CURLWS_BINARY; + /* 0x08 - first CLOSE fragment */ + case WSBIT_OPCODE_CLOSE: + failf(data, "[WS] invalid fragmented CLOSE frame"); + return 0; + /* 0x88 - unfragmented CLOSE */ + case (WSBIT_OPCODE_CLOSE | WSBIT_FIN): + return CURLWS_CLOSE; + /* 0x09 - first PING fragment */ + case WSBIT_OPCODE_PING: + failf(data, "[WS] invalid fragmented PING frame"); + return 0; + /* 0x89 - unfragmented PING */ + case (WSBIT_OPCODE_PING | WSBIT_FIN): + return CURLWS_PING; + /* 0x0a - first PONG fragment */ + case WSBIT_OPCODE_PONG: + failf(data, "[WS] invalid fragmented PONG frame"); + return 0; + /* 0x8a - unfragmented PONG */ + case (WSBIT_OPCODE_PONG | WSBIT_FIN): + return CURLWS_PONG; + /* invalid first byte */ + default: + if(firstbyte & WSBIT_RSV_MASK) + /* any of the reserved bits 0x40/0x20/0x10 are set */ + failf(data, "[WS] invalid reserved bits: %02x", firstbyte); + else + /* any of the reserved opcodes 0x3-0x7 or 0xb-0xf is used */ + failf(data, "[WS] invalid opcode: %02x", firstbyte); + return 0; } } static CURLcode ws_frame_flags2firstbyte(struct Curl_easy *data, unsigned int flags, bool contfragment, - unsigned char *pfirstbyte) + uint8_t *pfirstbyte) { *pfirstbyte = 0; switch(flags & ~CURLWS_OFFSET) { - case 0: - if(contfragment) { - CURL_TRC_WS(data, "no flags given; interpreting as continuation " - "fragment for compatibility"); - *pfirstbyte = (WSBIT_OPCODE_CONT | WSBIT_FIN); - return CURLE_OK; - } - failf(data, "[WS] no flags given"); - return CURLE_BAD_FUNCTION_ARGUMENT; - case CURLWS_CONT: - if(contfragment) { - infof(data, "[WS] setting CURLWS_CONT flag without message type is " - "supported for compatibility but highly discouraged"); - *pfirstbyte = WSBIT_OPCODE_CONT; - return CURLE_OK; - } - failf(data, "[WS] No ongoing fragmented message to continue"); - return CURLE_BAD_FUNCTION_ARGUMENT; - case CURLWS_TEXT: - *pfirstbyte = contfragment ? (WSBIT_OPCODE_CONT | WSBIT_FIN) - : (WSBIT_OPCODE_TEXT | WSBIT_FIN); - return CURLE_OK; - case (CURLWS_TEXT | CURLWS_CONT): - *pfirstbyte = contfragment ? WSBIT_OPCODE_CONT : WSBIT_OPCODE_TEXT; - return CURLE_OK; - case CURLWS_BINARY: - *pfirstbyte = contfragment ? (WSBIT_OPCODE_CONT | WSBIT_FIN) - : (WSBIT_OPCODE_BIN | WSBIT_FIN); - return CURLE_OK; - case (CURLWS_BINARY | CURLWS_CONT): - *pfirstbyte = contfragment ? WSBIT_OPCODE_CONT : WSBIT_OPCODE_BIN; - return CURLE_OK; - case CURLWS_CLOSE: - *pfirstbyte = WSBIT_OPCODE_CLOSE | WSBIT_FIN; - return CURLE_OK; - case (CURLWS_CLOSE | CURLWS_CONT): - failf(data, "[WS] CLOSE frame must not be fragmented"); - return CURLE_BAD_FUNCTION_ARGUMENT; - case CURLWS_PING: - *pfirstbyte = WSBIT_OPCODE_PING | WSBIT_FIN; + case 0: + if(contfragment) { + CURL_TRC_WS(data, "no flags given; interpreting as continuation " + "fragment for compatibility"); + *pfirstbyte = (WSBIT_OPCODE_CONT | WSBIT_FIN); return CURLE_OK; - case (CURLWS_PING | CURLWS_CONT): - failf(data, "[WS] PING frame must not be fragmented"); - return CURLE_BAD_FUNCTION_ARGUMENT; - case CURLWS_PONG: - *pfirstbyte = WSBIT_OPCODE_PONG | WSBIT_FIN; + } + failf(data, "[WS] no flags given"); + return CURLE_BAD_FUNCTION_ARGUMENT; + case CURLWS_CONT: + if(contfragment) { + infof(data, "[WS] setting CURLWS_CONT flag without message type is " + "supported for compatibility but highly discouraged"); + *pfirstbyte = WSBIT_OPCODE_CONT; return CURLE_OK; - case (CURLWS_PONG | CURLWS_CONT): - failf(data, "[WS] PONG frame must not be fragmented"); - return CURLE_BAD_FUNCTION_ARGUMENT; - default: - failf(data, "[WS] unknown flags: %x", flags); - return CURLE_BAD_FUNCTION_ARGUMENT; + } + failf(data, "[WS] No ongoing fragmented message to continue"); + return CURLE_BAD_FUNCTION_ARGUMENT; + case CURLWS_TEXT: + *pfirstbyte = contfragment ? (WSBIT_OPCODE_CONT | WSBIT_FIN) + : (WSBIT_OPCODE_TEXT | WSBIT_FIN); + return CURLE_OK; + case (CURLWS_TEXT | CURLWS_CONT): + *pfirstbyte = contfragment ? WSBIT_OPCODE_CONT : WSBIT_OPCODE_TEXT; + return CURLE_OK; + case CURLWS_BINARY: + *pfirstbyte = contfragment ? (WSBIT_OPCODE_CONT | WSBIT_FIN) + : (WSBIT_OPCODE_BIN | WSBIT_FIN); + return CURLE_OK; + case (CURLWS_BINARY | CURLWS_CONT): + *pfirstbyte = contfragment ? WSBIT_OPCODE_CONT : WSBIT_OPCODE_BIN; + return CURLE_OK; + case CURLWS_CLOSE: + *pfirstbyte = WSBIT_OPCODE_CLOSE | WSBIT_FIN; + return CURLE_OK; + case (CURLWS_CLOSE | CURLWS_CONT): + failf(data, "[WS] CLOSE frame must not be fragmented"); + return CURLE_BAD_FUNCTION_ARGUMENT; + case CURLWS_PING: + *pfirstbyte = WSBIT_OPCODE_PING | WSBIT_FIN; + return CURLE_OK; + case (CURLWS_PING | CURLWS_CONT): + failf(data, "[WS] PING frame must not be fragmented"); + return CURLE_BAD_FUNCTION_ARGUMENT; + case CURLWS_PONG: + *pfirstbyte = WSBIT_OPCODE_PONG | WSBIT_FIN; + return CURLE_OK; + case (CURLWS_PONG | CURLWS_CONT): + failf(data, "[WS] PONG frame must not be fragmented"); + return CURLE_BAD_FUNCTION_ARGUMENT; + default: + failf(data, "[WS] unknown flags: %x", flags); + return CURLE_BAD_FUNCTION_ARGUMENT; } } @@ -325,7 +318,7 @@ static CURLcode ws_send_raw_blocking(struct Curl_easy *data, struct websocket *ws, const char *buffer, size_t buflen); -typedef CURLcode ws_write_payload(const unsigned char *buf, size_t buflen, +typedef CURLcode ws_write_payload(const uint8_t *buf, size_t buflen, int frame_age, int frame_flags, curl_off_t payload_offset, curl_off_t payload_len, @@ -363,7 +356,7 @@ static CURLcode ws_dec_read_head(struct ws_decoder *dec, struct Curl_easy *data, struct bufq *inraw) { - const unsigned char *inbuf; + const uint8_t *inbuf; size_t inlen; while(Curl_bufq_peek(inraw, &inbuf, &inlen)) { @@ -455,13 +448,14 @@ static CURLcode ws_dec_read_head(struct ws_decoder *dec, failf(data, "[WS] frame length longer than 63 bit not supported"); return CURLE_RECV_ERROR; } - dec->payload_len = ((curl_off_t)dec->head[2] << 56) | + dec->payload_len = + (curl_off_t)dec->head[2] << 56 | (curl_off_t)dec->head[3] << 48 | (curl_off_t)dec->head[4] << 40 | (curl_off_t)dec->head[5] << 32 | (curl_off_t)dec->head[6] << 24 | (curl_off_t)dec->head[7] << 16 | - (curl_off_t)dec->head[8] << 8 | + (curl_off_t)dec->head[8] << 8 | dec->head[9]; break; default: @@ -485,16 +479,17 @@ static CURLcode ws_dec_pass_payload(struct ws_decoder *dec, ws_write_payload *write_cb, void *write_ctx) { - const unsigned char *inbuf; + const uint8_t *inbuf; size_t inlen; size_t nwritten; CURLcode result; - curl_off_t remain = dec->payload_len - dec->payload_offset; + size_t remain = curlx_sotouz_range(dec->payload_len - dec->payload_offset, + 0, SIZE_MAX); (void)data; while(remain && Curl_bufq_peek(inraw, &inbuf, &inlen)) { - if((curl_off_t)inlen > remain) - inlen = (size_t)remain; + if(inlen > remain) + inlen = remain; result = write_cb(inbuf, inlen, dec->frame_age, dec->frame_flags, dec->payload_offset, dec->payload_len, write_ctx, &nwritten); @@ -502,9 +497,10 @@ static CURLcode ws_dec_pass_payload(struct ws_decoder *dec, return result; Curl_bufq_skip(inraw, nwritten); dec->payload_offset += nwritten; - remain = dec->payload_len - dec->payload_offset; - CURL_TRC_WS(data, "passed %zu bytes payload, %" - FMT_OFF_T " remain", nwritten, remain); + remain = curlx_sotouz_range(dec->payload_len - dec->payload_offset, + 0, SIZE_MAX); + CURL_TRC_WS(data, "passed %zu bytes payload, %zu remain", + nwritten, remain); } return remain ? CURLE_AGAIN : CURLE_OK; @@ -541,7 +537,7 @@ static CURLcode ws_dec_pass(struct ws_decoder *dec, dec->state = WS_DEC_PAYLOAD; if(dec->payload_len == 0) { size_t nwritten; - const unsigned char tmp = '\0'; + const uint8_t tmp = '\0'; /* special case of a 0 length frame, need to write once */ result = write_cb(&tmp, 0, dec->frame_age, dec->frame_flags, 0, 0, write_ctx, &nwritten); @@ -614,7 +610,7 @@ static CURLcode ws_flush(struct Curl_easy *data, struct websocket *ws, bool blocking); static CURLcode ws_enc_send(struct Curl_easy *data, struct websocket *ws, - const unsigned char *buffer, + const uint8_t *buffer, size_t buflen, curl_off_t fragsize, unsigned int flags, @@ -624,7 +620,7 @@ static CURLcode ws_enc_add_pending(struct Curl_easy *data, static CURLcode ws_enc_add_cntrl(struct Curl_easy *data, struct websocket *ws, - const unsigned char *payload, + const uint8_t *payload, size_t plen, unsigned int frame_type) { @@ -651,19 +647,16 @@ static curl_off_t ws_payload_remain(curl_off_t payload_total, curl_off_t payload_offset, size_t payload_buffered) { - curl_off_t remain = payload_total - payload_offset; + curl_off_t buffered, remain = payload_total - payload_offset; if((payload_total < 0) || (payload_offset < 0) || (remain < 0)) return -1; -#if SIZEOF_SIZE_T >= SIZEOF_CURL_OFF_T - if(payload_buffered > (size_t)CURL_OFF_T_MAX) - return -1; -#endif - if(remain < (curl_off_t)payload_buffered) + buffered = curlx_uztoso(payload_buffered); + if(remain < buffered) return -1; - return remain - (curl_off_t)payload_buffered; + return remain - buffered; } -static CURLcode ws_cw_dec_next(const unsigned char *buf, size_t buflen, +static CURLcode ws_cw_dec_next(const uint8_t *buf, size_t buflen, int frame_age, int frame_flags, curl_off_t payload_offset, curl_off_t payload_len, @@ -729,7 +722,7 @@ static CURLcode ws_cw_write(struct Curl_easy *data, if(nbytes) { size_t nwritten; - result = Curl_bufq_write(&ctx->buf, (const unsigned char *)buf, + result = Curl_bufq_write(&ctx->buf, (const uint8_t *)buf, nbytes, &nwritten); if(result) { infof(data, "[WS] error adding data to buffer %d", result); @@ -775,7 +768,6 @@ static const struct Curl_cwtype ws_cw_decode = { sizeof(struct ws_cw_ctx) }; - static void ws_enc_info(struct ws_encoder *enc, struct Curl_easy *data, const char *msg) { @@ -827,8 +819,8 @@ static CURLcode ws_enc_add_frame(struct Curl_easy *data, curl_off_t payload_len, struct bufq *out) { - unsigned char firstb = 0; - unsigned char head[14]; + uint8_t firstb = 0; + uint8_t head[14]; CURLcode result; size_t hlen, nwritten; @@ -871,24 +863,24 @@ static CURLcode ws_enc_add_frame(struct Curl_easy *data, head[0] = enc->firstbyte = firstb; if(payload_len > 65535) { head[1] = 127 | WSBIT_MASK; - head[2] = (unsigned char)((payload_len >> 56) & 0xff); - head[3] = (unsigned char)((payload_len >> 48) & 0xff); - head[4] = (unsigned char)((payload_len >> 40) & 0xff); - head[5] = (unsigned char)((payload_len >> 32) & 0xff); - head[6] = (unsigned char)((payload_len >> 24) & 0xff); - head[7] = (unsigned char)((payload_len >> 16) & 0xff); - head[8] = (unsigned char)((payload_len >> 8) & 0xff); - head[9] = (unsigned char)(payload_len & 0xff); + head[2] = (uint8_t)((payload_len >> 56) & 0xff); + head[3] = (uint8_t)((payload_len >> 48) & 0xff); + head[4] = (uint8_t)((payload_len >> 40) & 0xff); + head[5] = (uint8_t)((payload_len >> 32) & 0xff); + head[6] = (uint8_t)((payload_len >> 24) & 0xff); + head[7] = (uint8_t)((payload_len >> 16) & 0xff); + head[8] = (uint8_t)((payload_len >> 8) & 0xff); + head[9] = (uint8_t)(payload_len & 0xff); hlen = 10; } else if(payload_len >= 126) { head[1] = 126 | WSBIT_MASK; - head[2] = (unsigned char)((payload_len >> 8) & 0xff); - head[3] = (unsigned char)(payload_len & 0xff); + head[2] = (uint8_t)((payload_len >> 8) & 0xff); + head[3] = (uint8_t)(payload_len & 0xff); hlen = 4; } else { - head[1] = (unsigned char)payload_len | WSBIT_MASK; + head[1] = (uint8_t)payload_len | WSBIT_MASK; hlen = 2; } @@ -897,7 +889,7 @@ static CURLcode ws_enc_add_frame(struct Curl_easy *data, /* 4 bytes random */ - result = Curl_rand(data, (unsigned char *)&enc->mask, sizeof(enc->mask)); + result = Curl_rand(data, (uint8_t *)&enc->mask, sizeof(enc->mask)); if(result) return result; @@ -943,11 +935,11 @@ static CURLcode ws_enc_write_head(struct Curl_easy *data, static CURLcode ws_enc_write_payload(struct ws_encoder *enc, struct Curl_easy *data, - const unsigned char *buf, size_t buflen, + const uint8_t *buf, size_t buflen, struct bufq *out, size_t *pnwritten) { CURLcode result; - size_t i, len, n; + size_t i, len, n, remain; *pnwritten = 0; if(Curl_bufq_is_full(out)) @@ -955,11 +947,12 @@ static CURLcode ws_enc_write_payload(struct ws_encoder *enc, /* not the most performant way to do this */ len = buflen; - if((curl_off_t)len > enc->payload_remain) - len = (size_t)enc->payload_remain; + remain = curlx_sotouz_range(enc->payload_remain, 0, SIZE_MAX); + if(remain < len) + len = remain; for(i = 0; i < len; ++i) { - unsigned char c = buf[i] ^ enc->mask[enc->xori]; + uint8_t c = buf[i] ^ enc->mask[enc->xori]; result = Curl_bufq_write(out, &c, 1, &n); if(result) { if((result != CURLE_AGAIN) || !i) @@ -990,7 +983,7 @@ static CURLcode ws_enc_add_pending(struct Curl_easy *data, (curl_off_t)ws->pending.payload_len, &ws->sendbuf); if(result) { - CURL_TRC_WS(data, "ws_enc_cntrl(), error addiong head: %d", + CURL_TRC_WS(data, "ws_enc_cntrl(), error adding head: %d", result); goto out; } @@ -1019,7 +1012,7 @@ static CURLcode ws_enc_add_pending(struct Curl_easy *data, static CURLcode ws_enc_send(struct Curl_easy *data, struct websocket *ws, - const unsigned char *buffer, + const uint8_t *buffer, size_t buflen, curl_off_t fragsize, unsigned int flags, @@ -1036,7 +1029,7 @@ static CURLcode ws_enc_send(struct Curl_easy *data, * that needs to be encoded into the buffer */ if(buflen < ws->sendbuf_payload) { /* We have been called with LESS buffer data than before. This - * is not how it's supposed too work. */ + * is not how it is supposed too work. */ failf(data, "[WS] curl_ws_send() called with smaller 'buflen' than " "bytes already buffered in previous call, %zu vs %zu", buflen, ws->sendbuf_payload); @@ -1167,8 +1160,7 @@ static CURLcode cr_ws_read(struct Curl_easy *data, if(ws->enc.payload_remain) { CURL_TRC_WS(data, "current frame, %" FMT_OFF_T " remaining", ws->enc.payload_remain); - if(ws->enc.payload_remain < (curl_off_t)blen) - blen = (size_t)ws->enc.payload_remain; + blen = curlx_sotouz_range(ws->enc.payload_remain, 0, blen); } result = Curl_creader_read(data, reader->next, buf, blen, &nread, &eos); @@ -1198,7 +1190,7 @@ static CURLcode cr_ws_read(struct Curl_easy *data, goto out; } - result = ws_enc_write_payload(&ws->enc, data, (unsigned char *)buf, + result = ws_enc_write_payload(&ws->enc, data, (uint8_t *)buf, nread, &ws->sendbuf, &n); if(result) goto out; @@ -1234,7 +1226,6 @@ static const struct Curl_crtype ws_cr_encode = { sizeof(struct cr_ws_ctx) }; - struct wsfield { const char *name; const char *val; @@ -1244,12 +1235,12 @@ CURLcode Curl_ws_request(struct Curl_easy *data, struct dynbuf *req) { unsigned int i; CURLcode result = CURLE_OK; - unsigned char rand[16]; + uint8_t rand[16]; char *randstr; size_t randlen; char keyval[40]; struct SingleRequest *k = &data->req; - struct wsfield heads[]= { + struct wsfield heads[] = { { /* The request MUST contain an |Upgrade| header field whose value MUST include the "websocket" keyword. */ @@ -1273,23 +1264,22 @@ CURLcode Curl_ws_request(struct Curl_easy *data, struct dynbuf *req) heads[2].val = &keyval[0]; /* 16 bytes random */ - result = Curl_rand(data, (unsigned char *)rand, sizeof(rand)); + result = Curl_rand(data, rand, sizeof(rand)); if(result) return result; - result = curlx_base64_encode((char *)rand, sizeof(rand), &randstr, &randlen); + result = curlx_base64_encode(rand, sizeof(rand), &randstr, &randlen); if(result) return result; DEBUGASSERT(randlen < sizeof(keyval)); if(randlen >= sizeof(keyval)) { - free(randstr); + curlx_free(randstr); return CURLE_FAILED_INIT; } - strcpy(keyval, randstr); - free(randstr); + curlx_strcopy(keyval, sizeof(keyval), randstr, randlen); + curlx_free(randstr); for(i = 0; !result && (i < CURL_ARRAYSIZE(heads)); i++) { if(!Curl_checkheaders(data, heads[i].name, strlen(heads[i].name))) { - result = curlx_dyn_addf(req, "%s: %s\r\n", heads[i].name, - heads[i].val); + result = curlx_dyn_addf(req, "%s: %s\r\n", heads[i].name, heads[i].val); } } data->state.http_hd_upgrade = TRUE; @@ -1305,7 +1295,7 @@ static void ws_conn_dtor(void *key, size_t klen, void *entry) (void)klen; Curl_bufq_free(&ws->recvbuf); Curl_bufq_free(&ws->sendbuf); - free(ws); + curlx_free(ws); } /* @@ -1325,7 +1315,7 @@ CURLcode Curl_ws_accept(struct Curl_easy *data, ws = Curl_conn_meta_get(data->conn, CURL_META_PROTO_WS_CONN); if(!ws) { size_t chunk_size = WS_CHUNK_SIZE; - ws = calloc(1, sizeof(*ws)); + ws = curlx_calloc(1, sizeof(*ws)); if(!ws) return CURLE_OUT_OF_MEMORY; #ifdef DEBUGBUILD @@ -1333,7 +1323,7 @@ CURLcode Curl_ws_accept(struct Curl_easy *data, const char *p = getenv("CURL_WS_CHUNK_SIZE"); if(p) { curl_off_t l; - if(!curlx_str_number(&p, &l, 1*1024*1024)) + if(!curlx_str_number(&p, &l, 1 * 1024 * 1024)) chunk_size = (size_t)l; } } @@ -1393,7 +1383,7 @@ CURLcode Curl_ws_accept(struct Curl_easy *data, /* In CONNECT_ONLY setup, the payloads from `mem` need to be received * when using `curl_ws_recv` later on after this transfer is already * marked as DONE. */ - result = Curl_bufq_write(&ws->recvbuf, (const unsigned char *)mem, + result = Curl_bufq_write(&ws->recvbuf, (const uint8_t *)mem, nread, &nwritten); if(result) goto out; @@ -1452,7 +1442,7 @@ CURLcode Curl_ws_accept(struct Curl_easy *data, struct ws_collect { struct Curl_easy *data; struct websocket *ws; - unsigned char *buffer; + uint8_t *buffer; size_t buflen; size_t bufidx; int frame_age; @@ -1462,7 +1452,7 @@ struct ws_collect { bool written; }; -static CURLcode ws_client_collect(const unsigned char *buf, size_t buflen, +static CURLcode ws_client_collect(const uint8_t *buf, size_t buflen, int frame_age, int frame_flags, curl_off_t payload_offset, curl_off_t payload_len, @@ -1519,7 +1509,7 @@ static CURLcode ws_client_collect(const unsigned char *buf, size_t buflen, } static CURLcode nw_in_recv(void *reader_ctx, - unsigned char *buf, size_t buflen, + uint8_t *buf, size_t buflen, size_t *pnread) { struct Curl_easy *data = reader_ctx; @@ -1560,7 +1550,6 @@ CURLcode curl_ws_recv(CURL *d, void *buffer, return CURLE_BAD_FUNCTION_ARGUMENT; } - memset(&ctx, 0, sizeof(ctx)); ctx.data = data; ctx.ws = ws; @@ -1629,7 +1618,7 @@ static CURLcode ws_flush(struct Curl_easy *data, struct websocket *ws, { if(!Curl_bufq_is_empty(&ws->sendbuf)) { CURLcode result; - const unsigned char *out; + const uint8_t *out; size_t outlen, n; #ifdef DEBUGBUILD /* Simulate a blocking send after this chunk has been sent */ @@ -1638,7 +1627,7 @@ static CURLcode ws_flush(struct Curl_easy *data, struct websocket *ws, const char *p = getenv("CURL_WS_CHUNK_EAGAIN"); if(p) { curl_off_t l; - if(!curlx_str_number(&p, &l, 1*1024*1024)) + if(!curlx_str_number(&p, &l, 1 * 1024 * 1024)) chunk_egain = (size_t)l; } #endif @@ -1704,7 +1693,7 @@ static CURLcode ws_send_raw_blocking(struct Curl_easy *data, CURL_TRC_WS(data, "ws_send_raw_blocking() partial, %zu left to send", buflen); - left_ms = Curl_timeleft(data, NULL, FALSE); + left_ms = Curl_timeleft_ms(data, FALSE); if(left_ms < 0) { failf(data, "[WS] Timeout waiting for socket becoming writable"); return CURLE_SEND_ERROR; @@ -1713,8 +1702,7 @@ static CURLcode ws_send_raw_blocking(struct Curl_easy *data, /* POLLOUT socket */ if(sock == CURL_SOCKET_BAD) return CURLE_SEND_ERROR; - ev = Curl_socket_check(CURL_SOCKET_BAD, CURL_SOCKET_BAD, sock, - left_ms ? left_ms : 500); + ev = SOCKET_WRITABLE(sock, left_ms ? left_ms : 500); if(ev < 0) { failf(data, "[WS] Error while waiting for socket becoming writable"); return CURLE_SEND_ERROR; @@ -1767,7 +1755,7 @@ CURLcode curl_ws_send(CURL *d, const void *buffer_arg, unsigned int flags) { struct websocket *ws; - const unsigned char *buffer = buffer_arg; + const uint8_t *buffer = buffer_arg; CURLcode result = CURLE_OK; struct Curl_easy *data = d; size_t ndummy; @@ -1849,7 +1837,6 @@ static CURLcode ws_setup_conn(struct Curl_easy *data, return Curl_http_setup_conn(data, conn); } - const struct curl_ws_frame *curl_ws_meta(CURL *d) { /* we only return something for websocket, called from within the callback @@ -1861,7 +1848,6 @@ const struct curl_ws_frame *curl_ws_meta(CURL *d) ws = Curl_conn_meta_get(data->conn, CURL_META_PROTO_WS_CONN); if(ws) return &ws->recvframe; - } return NULL; } @@ -1924,13 +1910,13 @@ const struct Curl_handler Curl_handler_ws = { Curl_http, /* do_it */ Curl_http_done, /* done */ ZERO_NULL, /* do_more */ - Curl_http_connect, /* connect_it */ + ZERO_NULL, /* connect_it */ ZERO_NULL, /* connecting */ ZERO_NULL, /* doing */ ZERO_NULL, /* proto_pollset */ - Curl_http_do_pollset, /* doing_pollset */ + Curl_http_doing_pollset, /* doing_pollset */ ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ + Curl_http_perform_pollset, /* perform_pollset */ ZERO_NULL, /* disconnect */ Curl_http_write_resp, /* write_resp */ Curl_http_write_resp_hd, /* write_resp_hd */ @@ -1951,13 +1937,13 @@ const struct Curl_handler Curl_handler_wss = { Curl_http, /* do_it */ Curl_http_done, /* done */ ZERO_NULL, /* do_more */ - Curl_http_connect, /* connect_it */ + ZERO_NULL, /* connect_it */ NULL, /* connecting */ ZERO_NULL, /* doing */ NULL, /* proto_pollset */ - Curl_http_do_pollset, /* doing_pollset */ + Curl_http_doing_pollset, /* doing_pollset */ ZERO_NULL, /* domore_pollset */ - ZERO_NULL, /* perform_pollset */ + Curl_http_perform_pollset, /* perform_pollset */ ZERO_NULL, /* disconnect */ Curl_http_write_resp, /* write_resp */ Curl_http_write_resp_hd, /* write_resp_hd */ @@ -1968,11 +1954,10 @@ const struct Curl_handler Curl_handler_wss = { CURLPROTO_WSS, /* protocol */ CURLPROTO_HTTP, /* family */ PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | /* flags */ - PROTOPT_USERPWDCTRL + PROTOPT_USERPWDCTRL }; #endif - #else CURLcode curl_ws_recv(CURL *curl, void *buffer, size_t buflen, @@ -2017,4 +2002,4 @@ CURL_EXTERN CURLcode curl_ws_start_frame(CURL *curl, return CURLE_NOT_BUILT_IN; } -#endif /* !CURL_DISABLE_WEBSOCKETS */ +#endif /* !CURL_DISABLE_WEBSOCKETS && !CURL_DISABLE_HTTP */ diff --git a/lib/ws.h b/lib/ws.h index b7655abbce74..a6e770694dee 100644 --- a/lib/ws.h +++ b/lib/ws.h @@ -38,10 +38,9 @@ extern const struct Curl_handler Curl_handler_ws; extern const struct Curl_handler Curl_handler_wss; #endif - #else -#define Curl_ws_request(x,y) CURLE_OK -#define Curl_ws_free(x) Curl_nop_stmt +#define Curl_ws_request(x, y) CURLE_OK +#define Curl_ws_free(x) Curl_nop_stmt #endif #endif /* HEADER_CURL_WS_H */ diff --git a/m4/curl-amissl.m4 b/m4/curl-amissl.m4 index a70a5366321e..aa3e3af37521 100644 --- a/m4/curl-amissl.m4 +++ b/m4/curl-amissl.m4 @@ -25,7 +25,7 @@ AC_DEFUN([CURL_WITH_AMISSL], [ AC_MSG_CHECKING([whether to enable Amiga native SSL/TLS (AmiSSL v5)]) if test "$HAVE_PROTO_BSDSOCKET_H" = "1"; then - if test "x$OPT_AMISSL" != xno; then + if test "x$OPT_AMISSL" != "xno"; then ssl_msg= AC_COMPILE_IFELSE([ AC_LANG_PROGRAM([[ @@ -33,8 +33,7 @@ if test "$HAVE_PROTO_BSDSOCKET_H" = "1"; then #include ]],[[ #if defined(AMISSL_CURRENT_VERSION) && defined(AMISSL_V3xx) && \ - (OPENSSL_VERSION_NUMBER >= 0x30000000L) && \ - defined(PROTO_AMISSL_H) + (OPENSSL_VERSION_NUMBER >= 0x30000000L) && defined(PROTO_AMISSL_H) return 0; #else #error not AmiSSL v5 / OpenSSL 3 @@ -43,7 +42,7 @@ if test "$HAVE_PROTO_BSDSOCKET_H" = "1"; then ],[ AC_MSG_RESULT([yes]) ssl_msg="AmiSSL" - test amissl != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes + test "amissl" != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes AMISSL_ENABLED=1 OPENSSL_ENABLED=1 # Use AmiSSL's built-in ca bundle @@ -53,8 +52,7 @@ if test "$HAVE_PROTO_BSDSOCKET_H" = "1"; then CURL_NETWORK_AND_TIME_LIBS="-lamisslstubs -lamisslauto $CURL_NETWORK_AND_TIME_LIBS" AC_DEFINE(USE_AMISSL, 1, [if AmiSSL is in use]) AC_DEFINE(USE_OPENSSL, 1, [if OpenSSL is in use]) - AC_CHECK_HEADERS(openssl/x509.h openssl/rsa.h openssl/crypto.h \ - openssl/pem.h openssl/ssl.h openssl/err.h) + AC_CHECK_HEADERS(openssl/rsa.h openssl/crypto.h openssl/pem.h openssl/ssl.h openssl/err.h) ],[ AC_MSG_RESULT([no]) ]) diff --git a/m4/curl-apple-sectrust.m4 b/m4/curl-apple-sectrust.m4 index 7ed2aa1e5bff..c70b7ac8cd61 100644 --- a/m4/curl-apple-sectrust.m4 +++ b/m4/curl-apple-sectrust.m4 @@ -24,7 +24,7 @@ AC_DEFUN([CURL_WITH_APPLE_SECTRUST], [ AC_MSG_CHECKING([whether to enable Apple OS native certificate validation]) -if test "x$OPT_APPLE_SECTRUST" = xyes; then +if test "x$OPT_APPLE_SECTRUST" = "xyes"; then AC_COMPILE_IFELSE([ AC_LANG_PROGRAM([[ #include @@ -41,10 +41,10 @@ if test "x$OPT_APPLE_SECTRUST" = xyes; then ],[ build_for_apple="no" ]) - if test "x$build_for_apple" == "xno"; then + if test "$build_for_apple" = "no"; then AC_MSG_ERROR([Apple SecTrust can only be enabled for Apple OS targets]) fi - if test "x$OPENSSL_ENABLED" == "x1" -o "x$GNUTLS_ENABLED" == "x1"; then + if test "$OPENSSL_ENABLED" = "1" || test "$GNUTLS_ENABLED" = "1"; then AC_MSG_RESULT(yes) AC_DEFINE(USE_APPLE_SECTRUST, 1, [enable Apple OS certificate validation]) APPLE_SECTRUST_ENABLED=1 diff --git a/m4/curl-compilers.m4 b/m4/curl-compilers.m4 index 0e4c4e2655b0..ff43f67f9914 100644 --- a/m4/curl-compilers.m4 +++ b/m4/curl-compilers.m4 @@ -88,7 +88,7 @@ AC_DEFUN([CURL_CHECK_COMPILER_CLANG], [ AC_MSG_RESULT([yes]) AC_MSG_CHECKING([if compiler is xlclang]) CURL_CHECK_DEF([__ibmxl__], [], [silent]) - if test "$curl_cv_have_def___ibmxl__" = "yes" ; then + if test "$curl_cv_have_def___ibmxl__" = "yes"; then dnl IBM's almost-compatible clang version AC_MSG_RESULT([yes]) compiler_id="XLCLANG" @@ -118,8 +118,8 @@ AC_DEFUN([CURL_CHECK_COMPILER_CLANG], [ clangvlo=`echo $clangver | cut -d . -f2` compiler_ver="$clangver" 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 "$appleclang" = "1" && test "$oldapple" = "0"; then + dnl Starting with Xcode 7 / clang 3.7, Apple clang does not tell its upstream version if test "$compiler_num" -ge '1700'; then compiler_num='1901' elif test "$compiler_num" -ge '1600'; then compiler_num='1700' elif test "$compiler_num" -ge '1500'; then compiler_num='1600' @@ -396,7 +396,8 @@ AC_DEFUN([CURL_CONVERT_INCLUDE_TO_ISYSTEM], [ AC_REQUIRE([CURL_CHECK_COMPILER])dnl AC_MSG_CHECKING([convert -I options to -isystem]) if test "$compiler_id" = "GNU_C" || - test "$compiler_id" = "CLANG" -o "$compiler_id" = "APPLECLANG"; then + test "$compiler_id" = "CLANG" || + test "$compiler_id" = "APPLECLANG"; then AC_MSG_RESULT([yes]) tmp_has_include="no" tmp_chg_FLAGS="$CFLAGS" @@ -475,7 +476,7 @@ AC_DEFUN([CURL_COMPILER_WORKS_IFELSE], [ ]) fi dnl only do runtime verification when not cross-compiling - if test "x$cross_compiling" != "xyes" && + if test "$cross_compiling" != "yes" && test "$tmp_compiler_works" = "yes"; then CURL_RUN_IFELSE([ AC_LANG_PROGRAM([[ @@ -555,7 +556,7 @@ AC_DEFUN([CURL_SET_COMPILER_BASIC_OPTS], [ # HP_UX_C) # - dnl Disallow run-time dereferencing of null pointers + dnl Disallow runtime dereferencing of null pointers tmp_CFLAGS="$tmp_CFLAGS -z" dnl Disable some remarks dnl #4227: padding struct with n bytes to align member @@ -632,7 +633,7 @@ AC_DEFUN([CURL_SET_COMPILER_BASIC_OPTS], [ squeeze tmp_CPPFLAGS squeeze tmp_CFLAGS # - if test ! -z "$tmp_CFLAGS" || test ! -z "$tmp_CPPFLAGS"; then + if test -n "$tmp_CFLAGS" || test -n "$tmp_CPPFLAGS"; then AC_MSG_CHECKING([if compiler accepts some basic options]) CPPFLAGS="$tmp_save_CPPFLAGS $tmp_CPPFLAGS" CFLAGS="$tmp_save_CFLAGS $tmp_CFLAGS" @@ -795,7 +796,11 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [ CLANG|APPLECLANG) # if test "$want_warnings" = "yes"; then - tmp_CFLAGS="$tmp_CFLAGS -pedantic" + if test "$compiler_num" -ge "302"; then + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [pedantic]) + else + tmp_CFLAGS="$tmp_CFLAGS -pedantic" + fi CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [all extra]) CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [pointer-arith write-strings]) CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [shadow]) @@ -936,12 +941,16 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [ if test "$compiler_num" -ge "1700"; then CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [cast-function-type-strict]) # with Apple clang it requires 16.0 or above fi + dnl clang 19 or later + if test "$compiler_num" -ge "1901"; then + tmp_CFLAGS="$tmp_CFLAGS -Wno-format-signedness" + fi dnl clang 20 or later - if test "$compiler_num" -ge "2000"; then + if test "$compiler_num" -ge "2001"; then CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [array-compare]) fi dnl clang 21 or later - if test "$compiler_num" -ge "2100"; then + if test "$compiler_num" -ge "2101"; then CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [c++-hidden-decl]) tmp_CFLAGS="$tmp_CFLAGS -Wno-implicit-void-ptr-cast" CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [tentative-definition-compat]) @@ -968,9 +977,13 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [ # dnl Do not enable -pedantic when cross-compiling with a gcc older dnl than 3.0, to avoid warnings from third party system headers. - if test "x$cross_compiling" != "xyes" || - test "$compiler_num" -ge "300"; then - tmp_CFLAGS="$tmp_CFLAGS -pedantic" + if test "$cross_compiling" != "yes" || + test "$compiler_num" -ge "300"; then + if test "$compiler_num" -ge "408"; then + CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [pedantic]) + else + tmp_CFLAGS="$tmp_CFLAGS -pedantic" + fi fi # dnl Set of options we believe *ALL* gcc versions support: @@ -981,7 +994,7 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [ if test "$compiler_num" -ge "104"; then CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [pointer-arith write-strings]) dnl If not cross-compiling with a gcc older than 3.0 - if test "x$cross_compiling" != "xyes" || + if test "$cross_compiling" != "yes" || test "$compiler_num" -ge "300"; then CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [unused shadow]) fi @@ -991,7 +1004,7 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [ if test "$compiler_num" -ge "207"; then CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [nested-externs]) dnl If not cross-compiling with a gcc older than 3.0 - if test "x$cross_compiling" != "xyes" || + if test "$cross_compiling" != "yes" || test "$compiler_num" -ge "300"; then CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [missing-declarations]) CURL_ADD_COMPILER_WARNINGS([tmp_CFLAGS], [missing-prototypes]) @@ -1115,6 +1128,7 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [ dnl Only gcc 5 or later if test "$compiler_num" -ge "500"; then tmp_CFLAGS="$tmp_CFLAGS -Warray-bounds=2" + tmp_CFLAGS="$tmp_CFLAGS -Wno-format-signedness" fi # dnl Only gcc 6 or later @@ -1168,7 +1182,7 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [ else dnl When cross-compiling with a gcc older than 3.0, disable dnl some warnings triggered on third party system headers. - if test "x$cross_compiling" = "xyes"; then + if test "$cross_compiling" = "yes"; then if test "$compiler_num" -ge "104"; then dnl gcc 1.4 or later tmp_CFLAGS="$tmp_CFLAGS -Wno-unused -Wno-shadow" @@ -1185,19 +1199,19 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [ tmp_CFLAGS="$tmp_CFLAGS -Wno-shadow" tmp_CFLAGS="$tmp_CFLAGS -Wno-unreachable-code" fi - if test "$compiler_num" -ge "402" -a "$compiler_num" -lt "406"; then + if test "$compiler_num" -ge "402" && test "$compiler_num" -lt "406"; then dnl GCC <4.6 do not support #pragma to suppress warnings locally. Disable globally instead. tmp_CFLAGS="$tmp_CFLAGS -Wno-overlength-strings" fi - if test "$compiler_num" -ge "400" -a "$compiler_num" -lt "407"; then + if test "$compiler_num" -ge "400" && test "$compiler_num" -lt "407"; then dnl https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84685 tmp_CFLAGS="$tmp_CFLAGS -Wno-missing-field-initializers" fi - if test "$compiler_num" -ge "403" -a "$compiler_num" -lt "408"; then + if test "$compiler_num" -ge "403" && test "$compiler_num" -lt "408"; then dnl Avoid false positives tmp_CFLAGS="$tmp_CFLAGS -Wno-type-limits" fi - if test "$compiler_num" -ge "501" -a "$compiler_num" -lt "505"; then + if test "$compiler_num" -ge "501" && test "$compiler_num" -lt "505"; then dnl Avoid false positives tmp_CFLAGS="$tmp_CFLAGS -Wno-conversion" fi @@ -1303,7 +1317,7 @@ AC_DEFUN([CURL_SET_COMPILER_WARNING_OPTS], [ squeeze tmp_CPPFLAGS squeeze tmp_CFLAGS # - if test ! -z "$tmp_CFLAGS" || test ! -z "$tmp_CPPFLAGS"; then + if test -n "$tmp_CFLAGS" || test -n "$tmp_CPPFLAGS"; then AC_MSG_CHECKING([if compiler accepts strict warning options]) CPPFLAGS="$tmp_save_CPPFLAGS $tmp_CPPFLAGS" CFLAGS="$tmp_save_CFLAGS $tmp_CFLAGS" @@ -1486,7 +1500,7 @@ AC_DEFUN([CURL_CHECK_COMPILER_SYMBOL_HIDING], [ GNU_C) dnl Only gcc 3.4 or later if test "$compiler_num" -ge "304"; then - if $CC --help --verbose 2>/dev/null | grep fvisibility= >/dev/null ; then + if $CC --help --verbose 2>/dev/null | grep fvisibility= >/dev/null; then tmp_EXTERN="__attribute__((__visibility__(\"default\")))" tmp_CFLAGS="-fvisibility=hidden" supports_symbol_hiding="yes" @@ -1496,7 +1510,7 @@ AC_DEFUN([CURL_CHECK_COMPILER_SYMBOL_HIDING], [ INTEL_UNIX_C) dnl Only icc 9.0 or later if test "$compiler_num" -ge "900"; then - if $CC --help --verbose 2>&1 | grep fvisibility= > /dev/null ; then + if $CC --help --verbose 2>&1 | grep fvisibility= > /dev/null; then tmp_save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fvisibility=hidden" AC_LINK_IFELSE([ @@ -1515,7 +1529,7 @@ AC_DEFUN([CURL_CHECK_COMPILER_SYMBOL_HIDING], [ fi ;; SUNPRO_C) - if $CC 2>&1 | grep flags >/dev/null && $CC -flags | grep xldscope= >/dev/null ; then + if $CC 2>&1 | grep flags >/dev/null && $CC -flags | grep xldscope= >/dev/null; then tmp_EXTERN="__global" tmp_CFLAGS="-xldscope=hidden" supports_symbol_hiding="yes" diff --git a/m4/curl-confopts.m4 b/m4/curl-confopts.m4 index 5149e8a34ae9..ff1b8b744ed3 100644 --- a/m4/curl-confopts.m4 +++ b/m4/curl-confopts.m4 @@ -73,7 +73,6 @@ dnl --enable-ares or --disable-ares, and dnl set shell variable want_ares as appropriate. AC_DEFUN([CURL_CHECK_OPTION_ARES], [ -dnl AC_BEFORE([$0],[CURL_CHECK_OPTION_THREADS])dnl AC_BEFORE([$0],[CURL_CHECK_LIB_ARES])dnl AC_MSG_CHECKING([whether to enable c-ares for DNS lookups]) OPT_ARES="default" @@ -93,7 +92,7 @@ AS_HELP_STRING([--disable-ares],[Disable c-ares for DNS lookups]), *) dnl --enable-ares option used want_ares="yes" - if test -n "$enableval" && test "$enableval" != "yes"; then + if test -n "$enableval" && test "x$enableval" != "xyes"; then want_ares_path="$enableval" fi ;; @@ -109,7 +108,6 @@ dnl --enable-curldebug or --disable-curldebug, and set dnl shell variable want_curldebug value as appropriate. AC_DEFUN([CURL_CHECK_OPTION_CURLDEBUG], [ - AC_BEFORE([$0],[CURL_CHECK_CURLDEBUG])dnl AC_MSG_CHECKING([whether to enable curl debug memory tracking]) OPT_CURLDEBUG_BUILD="default" AC_ARG_ENABLE(curldebug, @@ -392,15 +390,15 @@ AC_DEFUN([CURL_CHECK_NONBLOCKING_SOCKET], [ tst_method="unknown" AC_MSG_CHECKING([how to set a socket into non-blocking mode]) - if test "x$curl_cv_func_fcntl_o_nonblock" = "xyes"; then + if test "$curl_cv_func_fcntl_o_nonblock" = "yes"; then tst_method="fcntl O_NONBLOCK" - elif test "x$curl_cv_func_ioctl_fionbio" = "xyes"; then + elif test "$curl_cv_func_ioctl_fionbio" = "yes"; then tst_method="ioctl FIONBIO" - elif test "x$curl_cv_func_ioctlsocket_fionbio" = "xyes"; then + elif test "$curl_cv_func_ioctlsocket_fionbio" = "yes"; then tst_method="ioctlsocket FIONBIO" - elif test "x$curl_cv_func_ioctlsocket_camel_fionbio" = "xyes"; then + elif test "$curl_cv_func_ioctlsocket_camel_fionbio" = "yes"; then tst_method="IoctlSocket FIONBIO" - elif test "x$curl_cv_func_setsockopt_so_nonblock" = "xyes"; then + elif test "$curl_cv_func_setsockopt_so_nonblock" = "yes"; then tst_method="setsockopt SO_NONBLOCK" fi AC_MSG_RESULT([$tst_method]) @@ -433,7 +431,7 @@ AC_DEFUN([CURL_CONFIGURE_SYMBOL_HIDING], [ else AC_MSG_RESULT([no]) fi - AM_CONDITIONAL(DOING_CURL_SYMBOL_HIDING, test x$doing_symbol_hiding = xyes) + AM_CONDITIONAL(DOING_CURL_SYMBOL_HIDING, test "$doing_symbol_hiding" = "yes") AC_SUBST(CFLAG_CURL_SYMBOL_HIDING) ]) @@ -456,7 +454,7 @@ AC_DEFUN([CURL_CHECK_LIB_ARES], [ dnl c-ares library path has been specified ARES_PCDIR="$want_ares_path/lib/pkgconfig" CURL_CHECK_PKGCONFIG(libcares, [$ARES_PCDIR]) - if test "$PKGCONFIG" != "no" ; then + if test "$PKGCONFIG" != "no"; then ares_LIBS=`CURL_EXPORT_PCDIR([$ARES_PCDIR]) $PKGCONFIG --libs-only-l libcares` ares_LDFLAGS=`CURL_EXPORT_PCDIR([$ARES_PCDIR]) @@ -475,7 +473,7 @@ AC_DEFUN([CURL_CHECK_LIB_ARES], [ else dnl c-ares path not specified, use defaults CURL_CHECK_PKGCONFIG(libcares) - if test "$PKGCONFIG" != "no" ; then + if test "$PKGCONFIG" != "no"; then ares_LIBS=`$PKGCONFIG --libs-only-l libcares` ares_LDFLAGS=`$PKGCONFIG --libs-only-L libcares` ares_CPPFLAGS=`$PKGCONFIG --cflags-only-I libcares` diff --git a/m4/curl-functions.m4 b/m4/curl-functions.m4 index 3640f0c84ebb..52885d84a84c 100644 --- a/m4/curl-functions.m4 +++ b/m4/curl-functions.m4 @@ -508,7 +508,7 @@ AC_DEFUN([CURL_CHECK_FUNC_ALARM], [ AC_LANG_PROGRAM([[ $curl_includes_unistd ]],[[ - if(0 != alarm(0)) + if(alarm(0) != 0) return 1; ]]) ],[ @@ -599,7 +599,7 @@ AC_DEFUN([CURL_CHECK_FUNC_BASENAME], [ $curl_includes_libgen $curl_includes_unistd ]],[[ - if(0 != basename(0)) + if(basename(0) != 0) return 1; ]]) ],[ @@ -659,7 +659,7 @@ AC_DEFUN([CURL_CHECK_FUNC_CLOSESOCKET], [ AC_LANG_PROGRAM([[ $curl_includes_winsock2 ]],[[ - if(0 != closesocket(0)) + if(closesocket(0) != 0) return 1; ]]) ],[ @@ -689,7 +689,7 @@ AC_DEFUN([CURL_CHECK_FUNC_CLOSESOCKET], [ AC_LANG_PROGRAM([[ $curl_includes_winsock2 ]],[[ - if(0 != closesocket(0)) + if(closesocket(0) != 0) return 1; ]]) ],[ @@ -750,7 +750,7 @@ AC_DEFUN([CURL_CHECK_FUNC_CLOSESOCKET_CAMEL], [ $curl_includes_bsdsocket $curl_includes_sys_socket ]],[[ - if(0 != CloseSocket(0)) + if(CloseSocket(0) != 0) return 1; ]]) ],[ @@ -768,7 +768,7 @@ AC_DEFUN([CURL_CHECK_FUNC_CLOSESOCKET_CAMEL], [ $curl_includes_bsdsocket $curl_includes_sys_socket ]],[[ - if(0 != CloseSocket(0)) + if(CloseSocket(0) != 0) return 1; ]]) ],[ @@ -851,7 +851,7 @@ AC_DEFUN([CURL_CHECK_FUNC_FCNTL], [ AC_LANG_PROGRAM([[ $curl_includes_fcntl ]],[[ - if(0 != fcntl(0, 0, 0)) + if(fcntl(0, 0, 0) != 0) return 1; ]]) ],[ @@ -917,7 +917,7 @@ AC_DEFUN([CURL_CHECK_FUNC_FCNTL_O_NONBLOCK], [ $curl_includes_fcntl ]],[[ int flags = 0; - if(0 != fcntl(0, F_SETFL, flags | O_NONBLOCK)) + if(fcntl(0, F_SETFL, flags | O_NONBLOCK) != 0) return 1; ]]) ],[ @@ -1098,7 +1098,7 @@ AC_DEFUN([CURL_CHECK_FUNC_FSETXATTR], [ AC_LANG_PROGRAM([[ $curl_includes_sys_xattr ]],[[ - if(0 != fsetxattr(0, "", 0, 0, 0)) + if(fsetxattr(0, "", 0, 0, 0) != 0) return 1; ]]) ],[ @@ -1116,7 +1116,7 @@ AC_DEFUN([CURL_CHECK_FUNC_FSETXATTR], [ AC_LANG_PROGRAM([[ $curl_includes_sys_xattr ]],[[ - if(0 != fsetxattr(0, 0, 0, 0, 0, 0)) + if(fsetxattr(0, 0, 0, 0, 0, 0) != 0) return 1; ]]) ],[ @@ -1218,7 +1218,7 @@ AC_DEFUN([CURL_CHECK_FUNC_FTRUNCATE], [ AC_LANG_PROGRAM([[ $curl_includes_unistd ]],[[ - if(0 != ftruncate(0, 0)) + if(ftruncate(0, 0) != 0) return 1; ]]) ],[ @@ -1265,7 +1265,7 @@ dnl true, and usage has not been previously disallowed dnl with shell variable curl_disallow_getaddrinfo, then dnl HAVE_GETADDRINFO will be defined. Additionally when dnl HAVE_GETADDRINFO gets defined this will also attempt -dnl to find out if getaddrinfo happens to be threadsafe, +dnl to find out if getaddrinfo happens to be thread-safe, dnl defining HAVE_GETADDRINFO_THREADSAFE when true. AC_DEFUN([CURL_CHECK_FUNC_GETADDRINFO], [ @@ -1291,7 +1291,7 @@ AC_DEFUN([CURL_CHECK_FUNC_GETADDRINFO], [ $curl_includes_netdb ]],[[ struct addrinfo *ai = 0; - if(0 != getaddrinfo(0, 0, 0, &ai)) + if(getaddrinfo(0, 0, 0, &ai) != 0) return 1; ]]) ],[ @@ -1326,7 +1326,7 @@ AC_DEFUN([CURL_CHECK_FUNC_GETADDRINFO], [ $curl_includes_netdb ]],[[ struct addrinfo *ai = 0; - if(0 != getaddrinfo(0, 0, 0, &ai)) + if(getaddrinfo(0, 0, 0, &ai) != 0) return 1; ]]) ],[ @@ -1339,7 +1339,7 @@ AC_DEFUN([CURL_CHECK_FUNC_GETADDRINFO], [ fi # dnl only do runtime verification when not cross-compiling - if test "x$cross_compiling" != "xyes" && + if test "$cross_compiling" != "yes" && test "$tst_compi_getaddrinfo" = "yes"; then AC_MSG_CHECKING([if getaddrinfo seems to work]) CURL_RUN_IFELSE([ @@ -1414,8 +1414,8 @@ AC_DEFUN([CURL_CHECK_FUNC_GETADDRINFO], [ fi # if test "$curl_cv_func_getaddrinfo" = "yes"; then - AC_MSG_CHECKING([if getaddrinfo is threadsafe]) - if test "$curl_cv_apple" = 'yes'; then + AC_MSG_CHECKING([if getaddrinfo is thread-safe]) + if test "$curl_cv_apple" = "yes"; then dnl Darwin 6.0 and macOS 10.2.X and newer tst_tsafe_getaddrinfo="yes" fi @@ -1479,7 +1479,7 @@ AC_DEFUN([CURL_CHECK_FUNC_GETADDRINFO], [ AC_MSG_RESULT([$tst_tsafe_getaddrinfo]) if test "$tst_tsafe_getaddrinfo" = "yes"; then AC_DEFINE_UNQUOTED(HAVE_GETADDRINFO_THREADSAFE, 1, - [Define to 1 if the getaddrinfo function is threadsafe.]) + [Define to 1 if the getaddrinfo function is thread-safe.]) curl_cv_func_getaddrinfo_threadsafe="yes" else curl_cv_func_getaddrinfo_threadsafe="no" @@ -1537,7 +1537,7 @@ AC_DEFUN([CURL_CHECK_FUNC_GETHOSTBYNAME_R], [ $curl_includes_netdb $curl_includes_bsdsocket ]],[[ - if(0 != gethostbyname_r(0, 0, 0)) + if(gethostbyname_r(0, 0, 0) != 0) return 1; ]]) ],[ @@ -1556,7 +1556,7 @@ AC_DEFUN([CURL_CHECK_FUNC_GETHOSTBYNAME_R], [ $curl_includes_netdb $curl_includes_bsdsocket ]],[[ - if(0 != gethostbyname_r(0, 0, 0, 0, 0)) + if(gethostbyname_r(0, 0, 0, 0, 0) != 0) return 1; ]]) ],[ @@ -1575,7 +1575,7 @@ AC_DEFUN([CURL_CHECK_FUNC_GETHOSTBYNAME_R], [ $curl_includes_netdb $curl_includes_bsdsocket ]],[[ - if(0 != gethostbyname_r(0, 0, 0, 0, 0, 0)) + if(gethostbyname_r(0, 0, 0, 0, 0, 0) != 0) return 1; ]]) ],[ @@ -1660,7 +1660,7 @@ AC_DEFUN([CURL_CHECK_FUNC_GETHOSTNAME], [ $curl_includes_bsdsocket ]],[[ char s[1]; - if(0 != gethostname((void *)s, 0)) + if(gethostname((void *)s, 0) != 0) return 1; ]]) ],[ @@ -1695,7 +1695,7 @@ AC_DEFUN([CURL_CHECK_FUNC_GETHOSTNAME], [ $curl_includes_bsdsocket ]],[[ char s[1]; - if(0 != gethostname((void *)s, 0)) + if(gethostname((void *)s, 0) != 0) return 1; ]]) ],[ @@ -1727,7 +1727,7 @@ AC_DEFUN([CURL_CHECK_FUNC_GETHOSTNAME], [ int FUNCALLCONV gethostname($tst_arg1, $tst_arg2); ]],[[ char s[1]; - if(0 != gethostname(($tst_arg1)s, 0)) + if(gethostname(($tst_arg1)s, 0) != 0) return 1; ]]) ],[ @@ -1795,7 +1795,7 @@ AC_DEFUN([CURL_CHECK_FUNC_GETPEERNAME], [ $curl_includes_bsdsocket $curl_includes_sys_socket ]],[[ - if(0 != getpeername(0, (void *)0, (void *)0)) + if(getpeername(0, (void *)0, (void *)0) != 0) return 1; ]]) ],[ @@ -1829,7 +1829,7 @@ AC_DEFUN([CURL_CHECK_FUNC_GETPEERNAME], [ $curl_includes_bsdsocket $curl_includes_sys_socket ]],[[ - if(0 != getpeername(0, (void *)0, (void *)0)) + if(getpeername(0, (void *)0, (void *)0) != 0) return 1; ]]) ],[ @@ -1893,7 +1893,7 @@ AC_DEFUN([CURL_CHECK_FUNC_GETSOCKNAME], [ $curl_includes_bsdsocket $curl_includes_sys_socket ]],[[ - if(0 != getsockname(0, (void *)0, (void *)0)) + if(getsockname(0, (void *)0, (void *)0) != 0) return 1; ]]) ],[ @@ -1927,7 +1927,7 @@ AC_DEFUN([CURL_CHECK_FUNC_GETSOCKNAME], [ $curl_includes_bsdsocket $curl_includes_sys_socket ]],[[ - if(0 != getsockname(0, (void *)0, (void *)0)) + if(getsockname(0, (void *)0, (void *)0) != 0) return 1; ]]) ],[ @@ -2014,7 +2014,7 @@ AC_DEFUN([CURL_CHECK_FUNC_GETIFADDRS], [ AC_LANG_PROGRAM([[ $curl_includes_ifaddrs ]],[[ - if(0 != getifaddrs(0)) + if(getifaddrs(0) != 0) return 1; ]]) ],[ @@ -2027,7 +2027,7 @@ AC_DEFUN([CURL_CHECK_FUNC_GETIFADDRS], [ fi # dnl only do runtime verification when not cross-compiling - if test "x$cross_compiling" != "xyes" && + if test "$cross_compiling" != "yes" && test "$tst_compi_getifaddrs" = "yes"; then AC_MSG_CHECKING([if getifaddrs seems to work]) CURL_RUN_IFELSE([ @@ -2134,7 +2134,7 @@ AC_DEFUN([CURL_CHECK_FUNC_GMTIME_R], [ ]],[[ time_t tm = 1170352587; struct tm result; - if(0 != gmtime_r(&tm, &result)) + if(gmtime_r(&tm, &result) == 0) return 1; (void)result; ]]) @@ -2148,7 +2148,7 @@ AC_DEFUN([CURL_CHECK_FUNC_GMTIME_R], [ fi # dnl only do runtime verification when not cross-compiling - if test "x$cross_compiling" != "xyes" && + if test "$cross_compiling" != "yes" && test "$tst_compi_gmtime_r" = "yes"; then AC_MSG_CHECKING([if gmtime_r seems to work]) CURL_RUN_IFELSE([ @@ -2204,6 +2204,126 @@ AC_DEFUN([CURL_CHECK_FUNC_GMTIME_R], [ ]) +dnl CURL_CHECK_FUNC_LOCALTIME_R +dnl ------------------------------------------------- +dnl Verify if localtime_r is available, prototyped, can +dnl be compiled and seems to work. If all of these are +dnl true, and usage has not been previously disallowed +dnl with shell variable curl_disallow_localtime_r, then +dnl HAVE_LOCALTIME_R will be defined. + +AC_DEFUN([CURL_CHECK_FUNC_LOCALTIME_R], [ + AC_REQUIRE([CURL_INCLUDES_STDLIB])dnl + AC_REQUIRE([CURL_INCLUDES_TIME])dnl + # + tst_links_localtime_r="unknown" + tst_proto_localtime_r="unknown" + tst_compi_localtime_r="unknown" + tst_works_localtime_r="unknown" + tst_allow_localtime_r="unknown" + # + AC_MSG_CHECKING([if localtime_r can be linked]) + AC_LINK_IFELSE([ + AC_LANG_FUNC_LINK_TRY([localtime_r]) + ],[ + AC_MSG_RESULT([yes]) + tst_links_localtime_r="yes" + ],[ + AC_MSG_RESULT([no]) + tst_links_localtime_r="no" + ]) + # + if test "$tst_links_localtime_r" = "yes"; then + AC_MSG_CHECKING([if localtime_r is prototyped]) + AC_EGREP_CPP([localtime_r],[ + $curl_includes_time + ],[ + AC_MSG_RESULT([yes]) + tst_proto_localtime_r="yes" + ],[ + AC_MSG_RESULT([no]) + tst_proto_localtime_r="no" + ]) + fi + # + if test "$tst_proto_localtime_r" = "yes"; then + AC_MSG_CHECKING([if localtime_r is compilable]) + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([[ + $curl_includes_time + ]],[[ + time_t clock = 1170352587; + struct tm result; + if(localtime_r(&clock, &result) != 0) + return 1; + (void)result; + ]]) + ],[ + AC_MSG_RESULT([yes]) + tst_compi_localtime_r="yes" + ],[ + AC_MSG_RESULT([no]) + tst_compi_localtime_r="no" + ]) + fi + # + dnl only do runtime verification when not cross-compiling + if test "$cross_compiling" != "yes" && + test "$tst_compi_localtime_r" = "yes"; then + AC_MSG_CHECKING([if localtime_r seems to work]) + CURL_RUN_IFELSE([ + AC_LANG_PROGRAM([[ + $curl_includes_stdlib + $curl_includes_time + ]],[[ + time_t clock = 1170352587; + struct tm *tmp = 0; + struct tm result; + tmp = localtime_r(&clock, &result); + (void)result; + if(tmp) + return 0; + else + return 1; + ]]) + ],[ + AC_MSG_RESULT([yes]) + tst_works_localtime_r="yes" + ],[ + AC_MSG_RESULT([no]) + tst_works_localtime_r="no" + ]) + fi + # + if test "$tst_compi_localtime_r" = "yes" && + test "$tst_works_localtime_r" != "no"; then + AC_MSG_CHECKING([if localtime_r usage allowed]) + if test "x$curl_disallow_localtime_r" != "xyes"; then + AC_MSG_RESULT([yes]) + tst_allow_localtime_r="yes" + else + AC_MSG_RESULT([no]) + tst_allow_localtime_r="no" + fi + fi + # + AC_MSG_CHECKING([if localtime_r might be used]) + if test "$tst_links_localtime_r" = "yes" && + test "$tst_proto_localtime_r" = "yes" && + test "$tst_compi_localtime_r" = "yes" && + test "$tst_allow_localtime_r" = "yes" && + test "$tst_works_localtime_r" != "no"; then + AC_MSG_RESULT([yes]) + AC_DEFINE_UNQUOTED(HAVE_LOCALTIME_R, 1, + [Define to 1 if you have a working localtime_r function.]) + curl_cv_func_localtime_r="yes" + else + AC_MSG_RESULT([no]) + curl_cv_func_localtime_r="no" + fi +]) + + dnl CURL_CHECK_FUNC_INET_NTOP dnl ------------------------------------------------- dnl Verify if inet_ntop is available, prototyped, can @@ -2255,7 +2375,7 @@ AC_DEFUN([CURL_CHECK_FUNC_INET_NTOP], [ ]],[[ char ipv4res[sizeof("255.255.255.255")]; unsigned char ipv4a[5] = ""; - if(0 != inet_ntop(0, ipv4a, ipv4res, 0)) + if(inet_ntop(0, ipv4a, ipv4res, 0) != 0) return 1; ]]) ],[ @@ -2268,7 +2388,7 @@ AC_DEFUN([CURL_CHECK_FUNC_INET_NTOP], [ fi # dnl only do runtime verification when not cross-compiling - if test "x$cross_compiling" != "xyes" && + if test "$cross_compiling" != "yes" && test "$tst_compi_inet_ntop" = "yes"; then AC_MSG_CHECKING([if inet_ntop seems to work]) CURL_RUN_IFELSE([ @@ -2414,9 +2534,9 @@ AC_DEFUN([CURL_CHECK_FUNC_INET_PTON], [ AC_LANG_PROGRAM([[ $curl_includes_arpa_inet ]],[[ - unsigned char ipv4a[4+1] = ""; + unsigned char ipv4a[4 + 1] = ""; const char *ipv4src = "192.168.100.1"; - if(0 != inet_pton(0, ipv4src, ipv4a)) + if(inet_pton(0, ipv4src, ipv4a) != 0) return 1; ]]) ],[ @@ -2429,7 +2549,7 @@ AC_DEFUN([CURL_CHECK_FUNC_INET_PTON], [ fi # dnl only do runtime verification when not cross-compiling - if test "x$cross_compiling" != "xyes" && + if test "$cross_compiling" != "yes" && test "$tst_compi_inet_pton" = "yes"; then AC_MSG_CHECKING([if inet_pton seems to work]) CURL_RUN_IFELSE([ @@ -2438,45 +2558,45 @@ AC_DEFUN([CURL_CHECK_FUNC_INET_PTON], [ $curl_includes_arpa_inet $curl_includes_string ]],[[ - unsigned char ipv6a[16+1]; - unsigned char ipv4a[4+1]; + unsigned char ipv6a[16 + 1]; + unsigned char ipv4a[4 + 1]; const char *ipv6src = "fe80::214:4fff:fe0b:76c8"; const char *ipv4src = "192.168.100.1"; /* - */ memset(ipv4a, 1, sizeof(ipv4a)); - if(1 != inet_pton(AF_INET, ipv4src, ipv4a)) + if(inet_pton(AF_INET, ipv4src, ipv4a) != 1) return 1; /* fail */ /* - */ - if( (ipv4a[0] != 0xc0) || - (ipv4a[1] != 0xa8) || - (ipv4a[2] != 0x64) || - (ipv4a[3] != 0x01) || - (ipv4a[4] != 0x01) ) + if((ipv4a[0] != 0xc0) || + (ipv4a[1] != 0xa8) || + (ipv4a[2] != 0x64) || + (ipv4a[3] != 0x01) || + (ipv4a[4] != 0x01)) return 1; /* fail */ /* - */ memset(ipv6a, 1, sizeof(ipv6a)); - if(1 != inet_pton(AF_INET6, ipv6src, ipv6a)) + if(inet_pton(AF_INET6, ipv6src, ipv6a) != 1) return 1; /* fail */ /* - */ - if( (ipv6a[0] != 0xfe) || - (ipv6a[1] != 0x80) || - (ipv6a[8] != 0x02) || - (ipv6a[9] != 0x14) || - (ipv6a[10] != 0x4f) || - (ipv6a[11] != 0xff) || - (ipv6a[12] != 0xfe) || - (ipv6a[13] != 0x0b) || - (ipv6a[14] != 0x76) || - (ipv6a[15] != 0xc8) || - (ipv6a[16] != 0x01) ) + if((ipv6a[0] != 0xfe) || + (ipv6a[1] != 0x80) || + (ipv6a[8] != 0x02) || + (ipv6a[9] != 0x14) || + (ipv6a[10] != 0x4f) || + (ipv6a[11] != 0xff) || + (ipv6a[12] != 0xfe) || + (ipv6a[13] != 0x0b) || + (ipv6a[14] != 0x76) || + (ipv6a[15] != 0xc8) || + (ipv6a[16] != 0x01)) return 1; /* fail */ /* - */ - if( (ipv6a[2] != 0x0) || - (ipv6a[3] != 0x0) || - (ipv6a[4] != 0x0) || - (ipv6a[5] != 0x0) || - (ipv6a[6] != 0x0) || - (ipv6a[7] != 0x0) ) + if((ipv6a[2] != 0x0) || + (ipv6a[3] != 0x0) || + (ipv6a[4] != 0x0) || + (ipv6a[5] != 0x0) || + (ipv6a[6] != 0x0) || + (ipv6a[7] != 0x0)) return 1; /* fail */ /* - */ return 0; @@ -2565,7 +2685,7 @@ AC_DEFUN([CURL_CHECK_FUNC_IOCTL], [ AC_LANG_PROGRAM([[ $curl_includes_stropts ]],[[ - if(0 != ioctl(0, 0, 0)) + if(ioctl(0, 0, 0) != 0) return 1; ]]) ],[ @@ -2623,7 +2743,7 @@ AC_DEFUN([CURL_CHECK_FUNC_IOCTL_FIONBIO], [ $curl_includes_stropts ]],[[ int flags = 0; - if(0 != ioctl(0, FIONBIO, &flags)) + if(ioctl(0, FIONBIO, &flags) != 0) return 1; ]]) ],[ @@ -2680,7 +2800,7 @@ AC_DEFUN([CURL_CHECK_FUNC_IOCTL_SIOCGIFADDR], [ #include ]],[[ struct ifreq ifr; - if(0 != ioctl(0, SIOCGIFADDR, &ifr)) + if(ioctl(0, SIOCGIFADDR, &ifr) != 0) return 1; ]]) ],[ @@ -2738,7 +2858,7 @@ AC_DEFUN([CURL_CHECK_FUNC_IOCTLSOCKET], [ AC_LANG_PROGRAM([[ $curl_includes_winsock2 ]],[[ - if(0 != ioctlsocket(0, 0, 0)) + if(ioctlsocket(0, 0, 0) != 0) return 1; ]]) ],[ @@ -2768,7 +2888,7 @@ AC_DEFUN([CURL_CHECK_FUNC_IOCTLSOCKET], [ AC_LANG_PROGRAM([[ $curl_includes_winsock2 ]],[[ - if(0 != ioctlsocket(0, 0, 0)) + if(ioctlsocket(0, 0, 0) != 0) return 1; ]]) ],[ @@ -2827,7 +2947,7 @@ AC_DEFUN([CURL_CHECK_FUNC_IOCTLSOCKET_FIONBIO], [ $curl_includes_winsock2 ]],[[ unsigned long flags = 0; - if(0 != ioctlsocket(0, FIONBIO, &flags)) + if(ioctlsocket(0, FIONBIO, &flags) != 0) return 1; ]]) ],[ @@ -2884,7 +3004,7 @@ AC_DEFUN([CURL_CHECK_FUNC_IOCTLSOCKET_CAMEL], [ AC_LANG_PROGRAM([[ $curl_includes_bsdsocket ]],[[ - if(0 != IoctlSocket(0, 0, 0)) + if(IoctlSocket(0, 0, 0) != 0) return 1; ]]) ],[ @@ -2901,7 +3021,7 @@ AC_DEFUN([CURL_CHECK_FUNC_IOCTLSOCKET_CAMEL], [ AC_LANG_PROGRAM([[ $curl_includes_bsdsocket ]],[[ - if(0 != IoctlSocket(0, 0, 0)) + if(IoctlSocket(0, 0, 0) != 0) return 1; ]]) ],[ @@ -2959,7 +3079,7 @@ AC_DEFUN([CURL_CHECK_FUNC_IOCTLSOCKET_CAMEL_FIONBIO], [ $curl_includes_bsdsocket ]],[[ long flags = 0; - if(0 != IoctlSocket(0, FIONBIO, &flags)) + if(IoctlSocket(0, FIONBIO, &flags) != 0) return 1; ]]) ],[ @@ -3030,7 +3150,7 @@ AC_DEFUN([CURL_CHECK_FUNC_MEMRCHR], [ AC_LANG_PROGRAM([[ $curl_includes_string ]],[[ - if(0 != memrchr("", 0, 0)) + if(memrchr("", 0, 0) != 0) return 1; ]]) ],[ @@ -3062,7 +3182,7 @@ AC_DEFUN([CURL_CHECK_FUNC_MEMRCHR], [ AC_LANG_PROGRAM([[ $curl_includes_string ]],[[ - if(0 != memrchr("", 0, 0)) + if(memrchr("", 0, 0) != 0) return 1; ]]) ],[ @@ -3147,7 +3267,7 @@ AC_DEFUN([CURL_CHECK_FUNC_SIGACTION], [ AC_LANG_PROGRAM([[ $curl_includes_signal ]],[[ - if(0 != sigaction(0, 0, 0)) + if(sigaction(0, 0, 0) != 0) return 1; ]]) ],[ @@ -3232,7 +3352,7 @@ AC_DEFUN([CURL_CHECK_FUNC_SIGINTERRUPT], [ AC_LANG_PROGRAM([[ $curl_includes_signal ]],[[ - if(0 != siginterrupt(0, 0)) + if(siginterrupt(0, 0) != 0) return 1; ]]) ],[ @@ -3317,7 +3437,7 @@ AC_DEFUN([CURL_CHECK_FUNC_SIGNAL], [ AC_LANG_PROGRAM([[ $curl_includes_signal ]],[[ - if(0 != signal(0, 0)) + if(signal(0, 0) != 0) return 1; ]]) ],[ @@ -3391,7 +3511,7 @@ AC_DEFUN([CURL_CHECK_FUNC_SIGSETJMP], [ $curl_includes_setjmp ]],[[ sigjmp_buf env; - if(0 != sigsetjmp(env, 0)) + if(sigsetjmp(env, 0) != 0) return 1; ]]) ],[ @@ -3424,7 +3544,7 @@ AC_DEFUN([CURL_CHECK_FUNC_SIGSETJMP], [ $curl_includes_setjmp ]],[[ sigjmp_buf env; - if(0 != sigsetjmp(env, 0)) + if(sigsetjmp(env, 0) != 0) return 1; ]]) ],[ @@ -3487,7 +3607,7 @@ AC_DEFUN([CURL_CHECK_FUNC_SOCKET], [ $curl_includes_bsdsocket $curl_includes_sys_socket ]],[[ - if(0 != socket(0, 0, 0)) + if(socket(0, 0, 0) != 0) return 1; ]]) ],[ @@ -3521,7 +3641,7 @@ AC_DEFUN([CURL_CHECK_FUNC_SOCKET], [ $curl_includes_bsdsocket $curl_includes_sys_socket ]],[[ - if(0 != socket(0, 0, 0)) + if(socket(0, 0, 0) != 0) return 1; ]]) ],[ @@ -3607,7 +3727,7 @@ AC_DEFUN([CURL_CHECK_FUNC_SOCKETPAIR], [ $curl_includes_sys_socket ]],[[ int sv[2]; - if(0 != socketpair(0, 0, 0, sv)) + if(socketpair(0, 0, 0, sv) != 0) return 1; ]]) ],[ @@ -3692,7 +3812,7 @@ AC_DEFUN([CURL_CHECK_FUNC_STRCASECMP], [ AC_LANG_PROGRAM([[ $curl_includes_string ]],[[ - if(0 != strcasecmp("", "")) + if(strcasecmp("", "") != 0) return 1; ]]) ],[ @@ -3776,7 +3896,7 @@ AC_DEFUN([CURL_CHECK_FUNC_STRCMPI], [ AC_LANG_PROGRAM([[ $curl_includes_string ]],[[ - if(0 != strcmpi(0, 0)) + if(strcmpi(0, 0) != 0) return 1; ]]) ],[ @@ -3915,7 +4035,7 @@ dnl char *strerror_r(int errnum, char *workbuf, size_t bufsize); dnl dnl glibc-style strerror_r returns a pointer to the error string, dnl and might use the provided workbuf as a scratch area if needed. A -dnl quick test on a few systems shows that it's usually not used at all. +dnl quick test on a few systems shows that it is usually not used at all. dnl dnl POSIX-style strerror_r: dnl @@ -3971,7 +4091,7 @@ AC_DEFUN([CURL_CHECK_FUNC_STRERROR_R], [ $curl_includes_string ]],[[ char s[1]; - if(0 != strerror_r(0, s, 0)) + if(strerror_r(0, s, 0) != 0) return 1; ]]) ],[ @@ -3994,7 +4114,7 @@ AC_DEFUN([CURL_CHECK_FUNC_STRERROR_R], [ char *strerror_r(int errnum, char *workbuf, $arg3 bufsize); ]],[[ char s[1]; - if(0 != strerror_r(0, s, 0)) + if(strerror_r(0, s, 0) != 0) return 1; (void)s; ]]) @@ -4016,7 +4136,7 @@ AC_DEFUN([CURL_CHECK_FUNC_STRERROR_R], [ fi # dnl only do runtime verification when not cross-compiling - if test "x$cross_compiling" != "xyes" && + if test "$cross_compiling" != "yes" && test "$tst_glibc_strerror_r" = "yes"; then AC_MSG_CHECKING([if strerror_r seems to work]) CURL_RUN_IFELSE([ @@ -4057,7 +4177,7 @@ AC_DEFUN([CURL_CHECK_FUNC_STRERROR_R], [ int strerror_r(int errnum, char *resultbuf, $arg3 bufsize); ]],[[ char s[1]; - if(0 != strerror_r(0, s, 0)) + if(strerror_r(0, s, 0) != 0) return 1; (void)s; ]]) @@ -4079,7 +4199,7 @@ AC_DEFUN([CURL_CHECK_FUNC_STRERROR_R], [ fi # dnl only do runtime verification when not cross-compiling - if test "x$cross_compiling" != "xyes" && + if test "$cross_compiling" != "yes" && test "$tst_posix_strerror_r" = "yes"; then AC_MSG_CHECKING([if strerror_r seems to work]) CURL_RUN_IFELSE([ @@ -4213,7 +4333,7 @@ AC_DEFUN([CURL_CHECK_FUNC_STRICMP], [ AC_LANG_PROGRAM([[ $curl_includes_string ]],[[ - if(0 != stricmp(0, 0)) + if(stricmp(0, 0) != 0) return 1; ]]) ],[ @@ -4259,7 +4379,7 @@ dnl CURL_LIBRARY_PATH variable. It keeps the LD_LIBRARY_PATH dnl changes contained within this macro. AC_DEFUN([CURL_RUN_IFELSE], [ - if test "$curl_cv_apple" = 'yes'; then + if test "$curl_cv_apple" = "yes"; then AC_RUN_IFELSE([AC_LANG_SOURCE([$1])], $2, $3, $4) else oldcc=$CC @@ -4291,7 +4411,7 @@ AC_DEFUN([CURL_COVERAGE],[ coverage="$enableval") dnl if not gcc or clang switch off again - AS_IF([test "$compiler_id" != "GNU_C" -a "$compiler_id" != "CLANG" -a "$compiler_id" != "APPLECLANG"], coverage="no" ) + AS_IF([test "$compiler_id" != "GNU_C" && test "$compiler_id" != "CLANG" && test "$compiler_id" != "APPLECLANG"], coverage="no" ) AC_MSG_RESULT($coverage) if test "x$coverage" = "xyes"; then @@ -4380,8 +4500,8 @@ AC_DEFUN([CURL_SIZEOF], [ $2 ]],[ switch(0) { - case 0: - case (sizeof($1) == $typesize):; + case 0: + case (sizeof($1) == $typesize):; } ]) ],[ @@ -4390,11 +4510,11 @@ AC_DEFUN([CURL_SIZEOF], [ r=0 ]) dnl get out of the loop once matched - if test $r -gt 0; then + if test "$r" -gt 0; then break; fi done - if test $r -eq 0; then + if test "$r" -eq 0; then AC_MSG_ERROR([Failed to find size of $1]) fi AC_MSG_RESULT($r) diff --git a/m4/curl-gnutls.m4 b/m4/curl-gnutls.m4 index fb98f8d8fbb4..533d72129eb0 100644 --- a/m4/curl-gnutls.m4 +++ b/m4/curl-gnutls.m4 @@ -27,10 +27,10 @@ dnl check for GnuTLS dnl ---------------------------------------------------- AC_DEFUN([CURL_WITH_GNUTLS], [ -if test "x$OPT_GNUTLS" != xno; then +if test "x$OPT_GNUTLS" != "xno"; then ssl_msg= - if test X"$OPT_GNUTLS" != Xno; then + if test "x$OPT_GNUTLS" != "xno"; then addld="" addlib="" @@ -42,7 +42,7 @@ if test "x$OPT_GNUTLS" != xno; then dnl this is with no particular path given CURL_CHECK_PKGCONFIG(gnutls) - if test "$PKGCONFIG" != "no" ; then + if test "$PKGCONFIG" != "no"; then addlib=`$PKGCONFIG --libs-only-l gnutls` addld=`$PKGCONFIG --libs-only-L gnutls` addcflags=`$PKGCONFIG --cflags-only-I gnutls` @@ -60,7 +60,7 @@ if test "x$OPT_GNUTLS" != xno; then fi fi else - dnl this is with a given path, first check if there's a libgnutls-config + dnl this is with a given path, first check if there is a libgnutls-config dnl there and if not, make an educated guess cfg=$OPT_GNUTLS/bin/libgnutls-config check=`$cfg --version 2>/dev/null` @@ -74,7 +74,7 @@ if test "x$OPT_GNUTLS" != xno; then addlib=-lgnutls addld=-L$OPT_GNUTLS/lib$libsuff addcflags=-I$OPT_GNUTLS/include - version="" # we just don't know + version="" # we just do not know gtlslib=$OPT_GNUTLS/lib$libsuff fi fi @@ -100,36 +100,37 @@ if test "x$OPT_GNUTLS" != xno; then dnl this function is selected since it was introduced in 3.1.10 AC_CHECK_LIB(gnutls, gnutls_x509_crt_get_dn2, - [ + [ AC_DEFINE(USE_GNUTLS, 1, [if GnuTLS is enabled]) GNUTLS_ENABLED=1 USE_GNUTLS="yes" ssl_msg="GnuTLS" QUIC_ENABLED=yes - test gnutls != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes - ], - [ - LIBS="$CLEANLIBS" - CPPFLAGS="$CLEANCPPFLAGS" - ]) - - if test "x$USE_GNUTLS" = "xyes"; then + test "gnutls" != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes + ], + [ + LIBS="$CLEANLIBS" + CPPFLAGS="$CLEANCPPFLAGS" + LDFLAGS="$CLEANLDFLAGS" + LDFLAGSPC="$CLEANLDFLAGSPC" + ]) + + if test "$USE_GNUTLS" = "yes"; then AC_MSG_NOTICE([detected GnuTLS version $version]) check_for_ca_bundle=1 if test -n "$gtlslib"; then - dnl when shared libs were found in a path that the run-time - dnl linker doesn't search through, we need to add it to + dnl when shared libs were found in a path that the runtime + dnl linker does not search through, we need to add it to dnl CURL_LIBRARY_PATH to prevent further configure tests to fail dnl due to this - if test "x$cross_compiling" != "xyes"; then + if test "$cross_compiling" != "yes"; then CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$gtlslib" export CURL_LIBRARY_PATH AC_MSG_NOTICE([Added $gtlslib to CURL_LIBRARY_PATH]) fi fi - LIBCURL_PC_REQUIRES_PRIVATE="$LIBCURL_PC_REQUIRES_PRIVATE gnutls nettle" + LIBCURL_PC_REQUIRES_PRIVATE="$LIBCURL_PC_REQUIRES_PRIVATE gnutls" fi - fi fi dnl GNUTLS not disabled @@ -137,34 +138,81 @@ if test "x$OPT_GNUTLS" != xno; then test -z "$ssl_msg" || ssl_backends="${ssl_backends:+$ssl_backends, }$ssl_msg" fi -dnl --- -dnl Check which crypto backend GnuTLS uses -dnl --- - if test "$GNUTLS_ENABLED" = "1"; then + dnl --- + dnl Check which crypto backend GnuTLS uses + dnl --- USE_GNUTLS_NETTLE= # First check if we can detect either crypto library via transitive linking AC_CHECK_LIB(gnutls, nettle_MD5Init, [ USE_GNUTLS_NETTLE=1 ]) # If not, try linking directly to both of them to see if they are available - if test "$USE_GNUTLS_NETTLE" = ""; then - AC_CHECK_LIB(nettle, nettle_MD5Init, [ USE_GNUTLS_NETTLE=1 ]) + if test -z "$USE_GNUTLS_NETTLE"; then + + dnl this is with no particular path given + CURL_CHECK_PKGCONFIG(nettle) + + if test "$PKGCONFIG" != "no"; then + addlib=`$PKGCONFIG --libs-only-l nettle` + addld=`$PKGCONFIG --libs-only-L nettle` + addcflags=`$PKGCONFIG --cflags-only-I nettle` + version=`$PKGCONFIG --modversion nettle` + gtlslib=`echo $addld | $SED -e 's/^-L//'` + + if test -n "$addlib"; then + + CLEANLIBS="$LIBS" + CLEANCPPFLAGS="$CPPFLAGS" + CLEANLDFLAGS="$LDFLAGS" + CLEANLDFLAGSPC="$LDFLAGSPC" + + LIBS="$addlib $LIBS" + LDFLAGS="$LDFLAGS $addld" + LDFLAGSPC="$LDFLAGSPC $addld" + if test "$addcflags" != "-I/usr/include"; then + CPPFLAGS="$CPPFLAGS $addcflags" + fi + + AC_CHECK_LIB(nettle, nettle_MD5Init, + [ + USE_GNUTLS_NETTLE=1 + ], + [ + LIBS="$CLEANLIBS" + CPPFLAGS="$CLEANCPPFLAGS" + LDFLAGS="$CLEANLDFLAGS" + LDFLAGSPC="$CLEANLDFLAGSPC" + ]) + + if test "$USE_GNUTLS_NETTLE" = "1"; then + if test -z "$version"; then + version="unknown" + fi + AC_MSG_NOTICE([detected nettle version $version]) + fi + fi + fi + if test -z "$USE_GNUTLS_NETTLE"; then + AC_MSG_ERROR([GnuTLS found, but nettle was not found]) + fi + else + LIBS="-lnettle $LIBS" fi - if test "$USE_GNUTLS_NETTLE" = ""; then - AC_MSG_ERROR([GnuTLS found, but nettle was not found]) + + if test "$USE_GNUTLS_NETTLE" = "1"; then + LIBCURL_PC_REQUIRES_PRIVATE="$LIBCURL_PC_REQUIRES_PRIVATE nettle" fi - LIBS="-lnettle $LIBS" -fi -dnl --- -dnl We require GnuTLS with SRP support. -dnl --- -if test "$GNUTLS_ENABLED" = "1"; then + dnl --- + dnl We require GnuTLS with SRP support. + dnl + dnl In GnuTLS 3.8.0 (2023-02-10) and upper, this check always succeeds. + dnl Detecting actual TLS-SRP support needs poking the API at runtime. + dnl --- AC_CHECK_LIB(gnutls, gnutls_srp_verifier, [ AC_DEFINE(HAVE_GNUTLS_SRP, 1, [if you have the function gnutls_srp_verifier]) HAVE_GNUTLS_SRP=1 ]) fi - ]) diff --git a/m4/curl-mbedtls.m4 b/m4/curl-mbedtls.m4 index 519c29d79a69..7c5bccd22983 100644 --- a/m4/curl-mbedtls.m4 +++ b/m4/curl-mbedtls.m4 @@ -27,19 +27,19 @@ dnl check for mbedTLS dnl ---------------------------------------------------- AC_DEFUN([CURL_WITH_MBEDTLS], [ -if test "x$OPT_MBEDTLS" != xno; then +if test "x$OPT_MBEDTLS" != "xno"; then _cppflags=$CPPFLAGS _ldflags=$LDFLAGS _ldflagspc=$LDFLAGSPC ssl_msg= - if test X"$OPT_MBEDTLS" != Xno; then + if test "x$OPT_MBEDTLS" != "xno"; then - if test "$OPT_MBEDTLS" = "yes"; then + if test "x$OPT_MBEDTLS" = "xyes"; then OPT_MBEDTLS="" fi - if test -z "$OPT_MBEDTLS" ; then + if test -z "$OPT_MBEDTLS"; then dnl check for lib first without setting any new path AC_CHECK_LIB(mbedtls, mbedtls_havege_init, @@ -49,7 +49,7 @@ if test "x$OPT_MBEDTLS" != xno; then MBEDTLS_ENABLED=1 USE_MBEDTLS="yes" ssl_msg="mbedTLS" - test mbedtls != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes + test "mbedtls" != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes ], [], -lmbedx509 -lmbedcrypto) fi @@ -58,7 +58,7 @@ if test "x$OPT_MBEDTLS" != xno; then addcflags="" mbedtlslib="" - if test "x$USE_MBEDTLS" != "xyes"; then + if test "$USE_MBEDTLS" != "yes"; then dnl add the path and test again addld=-L$OPT_MBEDTLS/lib$libsuff addcflags=-I$OPT_MBEDTLS/include @@ -76,7 +76,7 @@ if test "x$OPT_MBEDTLS" != xno; then MBEDTLS_ENABLED=1 USE_MBEDTLS="yes" ssl_msg="mbedTLS" - test mbedtls != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes + test "mbedtls" != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes ], [ CPPFLAGS=$_cppflags @@ -85,18 +85,18 @@ if test "x$OPT_MBEDTLS" != xno; then ], -lmbedx509 -lmbedcrypto) fi - if test "x$USE_MBEDTLS" = "xyes"; then + if test "$USE_MBEDTLS" = "yes"; then AC_MSG_NOTICE([detected mbedTLS]) check_for_ca_bundle=1 LIBS="-lmbedtls -lmbedx509 -lmbedcrypto $LIBS" if test -n "$mbedtlslib"; then - dnl when shared libs were found in a path that the run-time - dnl linker doesn't search through, we need to add it to + dnl when shared libs were found in a path that the runtime + dnl linker does not search through, we need to add it to dnl CURL_LIBRARY_PATH to prevent further configure tests to fail dnl due to this - if test "x$cross_compiling" != "xyes"; then + if test "$cross_compiling" != "yes"; then CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$mbedtlslib" export CURL_LIBRARY_PATH AC_MSG_NOTICE([Added $mbedtlslib to CURL_LIBRARY_PATH]) @@ -106,6 +106,12 @@ if test "x$OPT_MBEDTLS" != xno; then if false; then LIBCURL_PC_REQUIRES_PRIVATE="$LIBCURL_PC_REQUIRES_PRIVATE mbedtls mbedx509 mbedcrypto" fi + + dnl Check DES support in mbedTLS <4. + AC_CHECK_FUNCS(mbedtls_des_crypt_ecb) + if test "$ac_cv_func_mbedtls_des_crypt_ecb" = 'yes'; then + HAVE_MBEDTLS_DES_CRYPT_ECB=1 + fi fi fi dnl mbedTLS not disabled diff --git a/m4/curl-openssl.m4 b/m4/curl-openssl.m4 index 56245c9c2a9e..be30c2c01be4 100644 --- a/m4/curl-openssl.m4 +++ b/m4/curl-openssl.m4 @@ -30,7 +30,7 @@ dnl Check for OpenSSL libraries and headers dnl ********************************************************************** AC_DEFUN([CURL_WITH_OPENSSL], [ -if test "x$OPT_OPENSSL" != xno; then +if test "x$OPT_OPENSSL" != "xno"; then ssl_msg= dnl backup the pre-ssl variables @@ -76,7 +76,7 @@ if test "x$OPT_OPENSSL" != xno; then PREFIX_OPENSSL=$OPT_OPENSSL dnl Try pkg-config even when cross-compiling. Since we - dnl specify PKG_CONFIG_LIBDIR we're only looking where + dnl specify PKG_CONFIG_LIBDIR we are only looking where dnl the user told us to look OPENSSL_PCDIR="$OPT_OPENSSL/lib/pkgconfig" if test -f "$OPENSSL_PCDIR/openssl.pc"; then @@ -102,7 +102,7 @@ if test "x$OPT_OPENSSL" != xno; then dnl in case pkg-config comes up empty, use what we got dnl via --with-openssl LIB_OPENSSL="$PREFIX_OPENSSL/lib$libsuff" - if test "$PREFIX_OPENSSL" != "/usr" ; then + if test "$PREFIX_OPENSSL" != "/usr"; then SSL_LDFLAGS="-L$LIB_OPENSSL" SSL_CPPFLAGS="-I$PREFIX_OPENSSL/include" fi @@ -113,7 +113,7 @@ if test "x$OPT_OPENSSL" != xno; then CURL_CHECK_PKGCONFIG(openssl, [$OPENSSL_PCDIR]) - if test "$PKGCONFIG" != "no" ; then + if test "$PKGCONFIG" != "no"; then SSL_LIBS=`CURL_EXPORT_PCDIR([$OPENSSL_PCDIR]) dnl $PKGCONFIG --libs-only-l --libs-only-other openssl 2>/dev/null` @@ -132,9 +132,9 @@ if test "x$OPT_OPENSSL" != xno; then dnl use the values pkg-config reported. This is here dnl instead of below with CPPFLAGS and LDFLAGS because we only dnl learn about this via pkg-config. If we only have - dnl the argument to --with-openssl we don't know what + dnl the argument to --with-openssl we do not know what dnl additional libs may be necessary. Hope that we - dnl don't need any. + dnl do not need any. LIBS="$SSL_LIBS $LIBS" fi fi @@ -148,12 +148,12 @@ if test "x$OPT_OPENSSL" != xno; then HAVECRYPTO="yes" LIBS="-lcrypto $LIBS" ],[ - if test -n "$LIB_OPENSSL" ; then + if test -n "$LIB_OPENSSL"; then LDFLAGS="$CLEANLDFLAGS -L$LIB_OPENSSL" LDFLAGSPC="$CLEANLDFLAGSPC -L$LIB_OPENSSL" fi - if test "$PKGCONFIG" = "no" -a -n "$PREFIX_OPENSSL" ; then - # only set this if pkg-config wasn't used + if test "$PKGCONFIG" = "no" && test -n "$PREFIX_OPENSSL"; then + # only set this if pkg-config was not used CPPFLAGS="$CLEANCPPFLAGS -I$PREFIX_OPENSSL/include" fi # Linking previously failed, try extra paths from --with-openssl or @@ -203,33 +203,32 @@ if test "x$OPT_OPENSSL" != xno; then ]) ]) - if test X"$HAVECRYPTO" = X"yes"; then + if test "$HAVECRYPTO" = "yes"; then dnl This is only reasonable to do if crypto actually is there: check for dnl SSL libs NOTE: it is important to do this AFTER the crypto lib AC_CHECK_LIB(ssl, SSL_connect) - if test "$ac_cv_lib_ssl_SSL_connect" = yes; then + if test "$ac_cv_lib_ssl_SSL_connect" = "yes"; then dnl Have the libraries--check for OpenSSL headers - AC_CHECK_HEADERS(openssl/x509.h openssl/rsa.h openssl/crypto.h \ - openssl/pem.h openssl/ssl.h openssl/err.h, + AC_CHECK_HEADERS(openssl/rsa.h openssl/crypto.h openssl/pem.h openssl/ssl.h openssl/err.h, ssl_msg="OpenSSL" - test openssl != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes + test "openssl" != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes OPENSSL_ENABLED=1 AC_DEFINE(USE_OPENSSL, 1, [if OpenSSL is in use])) fi - if test X"$OPENSSL_ENABLED" != X"1"; then + if test "$OPENSSL_ENABLED" != "1"; then LIBS="$CLEANLIBS" fi - if test X"$OPT_OPENSSL" != Xoff && + if test "x$OPT_OPENSSL" != "xoff" && test "$OPENSSL_ENABLED" != "1"; then AC_MSG_ERROR([OpenSSL libs and/or directories were not found where specified!]) fi fi - if test X"$OPENSSL_ENABLED" = X"1"; then + if test "$OPENSSL_ENABLED" = "1"; then dnl These can only exist if OpenSSL exists AC_MSG_CHECKING([for BoringSSL]) @@ -282,23 +281,22 @@ if test "x$OPT_OPENSSL" != xno; then AC_MSG_RESULT([no]) ]) - AC_MSG_CHECKING([for OpenSSL >= v3]) - AC_COMPILE_IFELSE([ - AC_LANG_PROGRAM([[ - #include - ]],[[ - #if (OPENSSL_VERSION_NUMBER >= 0x30000000L) - return 0; - #else - #error older than 3 - #endif - ]]) - ],[ - AC_MSG_RESULT([yes]) - ssl_msg="OpenSSL v3+" - ],[ - AC_MSG_RESULT([no]) - ]) + if test "$ssl_msg" = 'OpenSSL'; then + AC_MSG_CHECKING([for OpenSSL >= v3]) + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([[ + #include + ]],[[ + #if (OPENSSL_VERSION_NUMBER >= 0x30000000L) + return 0; + #else + #error older than 3 + #endif + ]]) + ],[],[ + AC_MSG_ERROR([OpenSSL 3.0.0 or upper required.]) + ]) + fi fi dnl is this OpenSSL (fork) providing the original QUIC API? @@ -317,10 +315,10 @@ if test "x$OPT_OPENSSL" != xno; then 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 - dnl linker doesn't search through, we need to add it to CURL_LIBRARY_PATH + dnl when the ssl shared libs were found in a path that the runtime + dnl linker does not search through, we need to add it to CURL_LIBRARY_PATH dnl to prevent further configure tests to fail due to this - if test "x$cross_compiling" != "xyes"; then + if test "$cross_compiling" != "yes"; then CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$LIB_OPENSSL" export CURL_LIBRARY_PATH AC_MSG_NOTICE([Added $LIB_OPENSSL to CURL_LIBRARY_PATH]) @@ -333,17 +331,38 @@ if test "x$OPT_OPENSSL" != xno; then test -z "$ssl_msg" || ssl_backends="${ssl_backends:+$ssl_backends, }$ssl_msg" fi -if test X"$OPT_OPENSSL" != Xno && +if test "x$OPT_OPENSSL" != "xno" && test "$OPENSSL_ENABLED" != "1"; then AC_MSG_NOTICE([OPT_OPENSSL: $OPT_OPENSSL]) AC_MSG_NOTICE([OPENSSL_ENABLED: $OPENSSL_ENABLED]) AC_MSG_ERROR([--with-openssl was given but OpenSSL could not be detected]) fi -dnl --- -dnl We require OpenSSL with SRP support. -dnl --- if test "$OPENSSL_ENABLED" = "1"; then + dnl --- + dnl We check OpenSSL for DES support. + dnl --- + AC_MSG_CHECKING([for DES support in OpenSSL]) + AC_LINK_IFELSE([ + AC_LANG_PROGRAM([[ + #ifndef OPENSSL_SUPPRESS_DEPRECATED + #define OPENSSL_SUPPRESS_DEPRECATED + #endif + #include + ]],[[ + DES_ecb_encrypt(0, 0, 0, DES_ENCRYPT); + ]]) + ],[ + AC_MSG_RESULT([yes]) + AC_DEFINE(HAVE_DES_ECB_ENCRYPT, 1, [if you have the function DES_ecb_encrypt]) + HAVE_DES_ECB_ENCRYPT=1 + ],[ + AC_MSG_RESULT([no]) + ]) + + dnl --- + dnl We require OpenSSL with SRP support. + dnl --- AC_MSG_CHECKING([for SRP support in OpenSSL]) AC_LINK_IFELSE([ AC_LANG_PROGRAM([[ @@ -362,26 +381,22 @@ if test "$OPENSSL_ENABLED" = "1"; then ],[ AC_MSG_RESULT([no]) ]) -fi -dnl --- -dnl Whether the OpenSSL configuration will be loaded automatically -dnl --- -if test X"$OPENSSL_ENABLED" = X"1"; then + dnl --- + dnl Whether the OpenSSL configuration will be loaded automatically + dnl --- AC_ARG_ENABLE(openssl-auto-load-config, AS_HELP_STRING([--enable-openssl-auto-load-config],[Enable automatic loading of OpenSSL configuration]) AS_HELP_STRING([--disable-openssl-auto-load-config],[Disable automatic loading of OpenSSL configuration]), - [ if test X"$enableval" = X"no"; then + [ if test "x$enableval" = "xno"; then AC_MSG_NOTICE([automatic loading of OpenSSL configuration disabled]) - AC_DEFINE(CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG, 1, [if the OpenSSL configuration won't be loaded automatically]) + AC_DEFINE(CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG, 1, [if the OpenSSL configuration will not be loaded automatically]) fi ]) -fi -dnl --- -dnl We may use OpenSSL QUIC. -dnl --- -if test "$OPENSSL_ENABLED" = "1"; then + dnl --- + dnl We may use OpenSSL QUIC. + dnl --- AC_MSG_CHECKING([for QUIC support and OpenSSL >= 3.3]) AC_LINK_IFELSE([ AC_LANG_PROGRAM([[ diff --git a/m4/curl-override.m4 b/m4/curl-override.m4 index e36c0c6c7428..e84b4ca5faeb 100644 --- a/m4/curl-override.m4 +++ b/m4/curl-override.m4 @@ -42,7 +42,7 @@ AC_BEFORE([$0],[AC_PROG_LIBTOOL]) dnl Override Autoconf's AC_LANG_PROGRAM (C) dnl ------------------------------------------------- dnl This is done to prevent compiler warning -dnl 'function declaration isn't a prototype' +dnl 'function declaration is not a prototype' dnl in function main. This requires at least dnl a C89 compiler and does not support K&R. diff --git a/m4/curl-reentrant.m4 b/m4/curl-reentrant.m4 index 95e539c152e6..501278eec341 100644 --- a/m4/curl-reentrant.m4 +++ b/m4/curl-reentrant.m4 @@ -184,6 +184,7 @@ AC_DEFUN([CURL_CHECK_NEED_REENTRANT_STRERROR_R], [ fi ]) + dnl CURL_CHECK_NEED_REENTRANT_GETHOSTBYNAME_R dnl ------------------------------------------------- dnl Checks if the preprocessor _REENTRANT definition @@ -359,7 +360,7 @@ _EOF dnl CURL_CONFIGURE_REENTRANT dnl ------------------------------------------------- dnl This first checks if the preprocessor _REENTRANT -dnl symbol is already defined. If it isn't currently +dnl symbol is already defined. If it is not currently dnl defined a set of checks are performed to verify dnl if its definition is required to make visible to dnl the compiler a set of *_r functions. Finally, if @@ -421,7 +422,7 @@ AC_DEFUN([CURL_CONFIGURE_REENTRANT], [ dnl CURL_CONFIGURE_THREAD_SAFE dnl ------------------------------------------------- dnl This first checks if the preprocessor _THREAD_SAFE -dnl symbol is already defined. If it isn't currently +dnl symbol is already defined. If it is not currently dnl defined a set of checks are performed to verify dnl if its definition is required. Finally, if dnl _THREAD_SAFE is already defined or needed it takes diff --git a/m4/curl-rustls.m4 b/m4/curl-rustls.m4 index 8abcc6544bc5..f1b5d6b1df44 100644 --- a/m4/curl-rustls.m4 +++ b/m4/curl-rustls.m4 @@ -27,7 +27,7 @@ dnl ---------------------------------------------------- dnl check for Rustls dnl ---------------------------------------------------- -if test "x$OPT_RUSTLS" != xno; then +if test "x$OPT_RUSTLS" != "xno"; then ssl_msg= dnl backup the pre-ssl variables @@ -83,14 +83,14 @@ if test "x$OPT_RUSTLS" != xno; then CPPFLAGS="$CPPFLAGS $addcflags" fi - if test "$curl_cv_apple" = 'yes'; then + if test "$curl_cv_apple" = "yes"; then RUSTLS_LDFLAGS="-framework Security -framework Foundation" else RUSTLS_LDFLAGS="-lpthread -ldl -lm" fi LIB_RUSTLS="$PREFIX_RUSTLS/lib$libsuff" - if test "$PREFIX_RUSTLS" != "/usr" ; then + if test "$PREFIX_RUSTLS" != "/usr"; then SSL_LDFLAGS="-L$LIB_RUSTLS $RUSTLS_LDFLAGS" SSL_CPPFLAGS="-I$PREFIX_RUSTLS/include" fi @@ -108,7 +108,7 @@ if test "x$OPT_RUSTLS" != xno; then CURL_CHECK_PKGCONFIG(rustls, [$RUSTLS_PCDIR]) - if test "$PKGCONFIG" != "no" ; then + if test "$PKGCONFIG" != "no"; then SSL_LIBS=`CURL_EXPORT_PCDIR([$RUSTLS_PCDIR]) dnl $PKGCONFIG --libs-only-l --libs-only-other rustls 2>/dev/null` @@ -127,16 +127,16 @@ if test "x$OPT_RUSTLS" != xno; then dnl use the values pkg-config reported. This is here dnl instead of below with CPPFLAGS and LDFLAGS because we only dnl learn about this via pkg-config. If we only have - dnl the argument to --with-rustls we don't know what + dnl the argument to --with-rustls we do not know what dnl additional libs may be necessary. Hope that we - dnl don't need any. + dnl do not need any. LIBS="$SSL_LIBS $LIBS" link_pkgconfig=1 ssl_msg="Rustls" AC_DEFINE(USE_RUSTLS, 1, [if Rustls is enabled]) USE_RUSTLS="yes" RUSTLS_ENABLED=1 - test rustls != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes + test "rustls" != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes else AC_MSG_ERROR([pkg-config: Could not find Rustls]) fi @@ -152,16 +152,16 @@ if test "x$OPT_RUSTLS" != xno; then LDFLAGS="$CLEANLDFLAGS $SSL_LDFLAGS" LDFLAGSPC="$CLEANLDFLAGSPC $SSL_LDFLAGS" - if test "x$USE_RUSTLS" = "xyes"; then + if test "$USE_RUSTLS" = "yes"; then AC_MSG_NOTICE([detected Rustls]) check_for_ca_bundle=1 if test -n "$LIB_RUSTLS"; then - dnl when shared libs were found in a path that the run-time + dnl when shared libs were found in a path that the runtime dnl linker does not search through, we need to add it to dnl CURL_LIBRARY_PATH so that further configure tests do not dnl fail due to this - if test "x$cross_compiling" != "xyes"; then + if test "$cross_compiling" != "yes"; then CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$LIB_RUSTLS" export CURL_LIBRARY_PATH AC_MSG_NOTICE([Added $LIB_RUSTLS to CURL_LIBRARY_PATH]) @@ -177,7 +177,7 @@ if test "x$OPT_RUSTLS" != xno; then RUSTLS_ENABLED=1 USE_RUSTLS="yes" ssl_msg="Rustls" - test rustls != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes + test "rustls" != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes ], AC_MSG_ERROR([--with-rustls was specified but could not find compatible Rustls.]), $RUSTLS_LDFLAGS) @@ -185,7 +185,7 @@ if test "x$OPT_RUSTLS" != xno; then test -z "$ssl_msg" || ssl_backends="${ssl_backends:+$ssl_backends, }$ssl_msg" - if test X"$OPT_RUSTLS" != Xno && + if test "x$OPT_RUSTLS" != "xno" && test "$RUSTLS_ENABLED" != "1"; then AC_MSG_NOTICE([OPT_RUSTLS: $OPT_RUSTLS]) AC_MSG_NOTICE([RUSTLS_ENABLED: $RUSTLS_ENABLED]) diff --git a/m4/curl-schannel.m4 b/m4/curl-schannel.m4 index 1aa66dc2c84a..c67098fa113e 100644 --- a/m4/curl-schannel.m4 +++ b/m4/curl-schannel.m4 @@ -24,17 +24,17 @@ AC_DEFUN([CURL_WITH_SCHANNEL], [ AC_MSG_CHECKING([whether to enable Windows native SSL/TLS]) -if test "x$OPT_SCHANNEL" != xno; then +if test "x$OPT_SCHANNEL" != "xno"; then ssl_msg= if test "x$OPT_SCHANNEL" != "xno" && - test "x$curl_cv_native_windows" = "xyes"; then - if test "$curl_cv_winuwp" = 'yes'; then + test "$curl_cv_native_windows" = "yes"; then + if test "$curl_cv_winuwp" = "yes"; then AC_MSG_ERROR([UWP does not support Schannel.]) fi AC_MSG_RESULT(yes) AC_DEFINE(USE_SCHANNEL, 1, [to enable Windows native SSL/TLS support]) ssl_msg="Schannel" - test schannel != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes + test "schannel" != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes SCHANNEL_ENABLED=1 # --with-schannel implies --enable-sspi AC_DEFINE(USE_WINDOWS_SSPI, 1, [to enable SSPI support]) diff --git a/m4/curl-sysconfig.m4 b/m4/curl-sysconfig.m4 index f5ebe0391b20..7ad1285ef2df 100644 --- a/m4/curl-sysconfig.m4 +++ b/m4/curl-sysconfig.m4 @@ -40,7 +40,7 @@ AC_MSG_CHECKING([whether to link macOS CoreFoundation, CoreServices, and SystemC ],[ build_for_macos="no" ]) - if test "x$build_for_macos" != xno; then + if test "$build_for_macos" != "no"; then AC_MSG_RESULT(yes) SYSCONFIG_LDFLAGS='-framework CoreFoundation -framework CoreServices -framework SystemConfiguration' LDFLAGS="$LDFLAGS $SYSCONFIG_LDFLAGS" diff --git a/m4/curl-wolfssl.m4 b/m4/curl-wolfssl.m4 index e2c58a94af5d..4cbc6f5c0c4e 100644 --- a/m4/curl-wolfssl.m4 +++ b/m4/curl-wolfssl.m4 @@ -36,14 +36,14 @@ case "$OPT_WOLFSSL" in ;; esac -if test "x$OPT_WOLFSSL" != xno; then +if test "$OPT_WOLFSSL" != "no"; then _cppflags=$CPPFLAGS _ldflags=$LDFLAGS _ldflagspc=$LDFLAGSPC ssl_msg= - if test X"$OPT_WOLFSSL" != Xno; then + if test "$OPT_WOLFSSL" != "no"; then if test "$OPT_WOLFSSL" = "yes"; then OPT_WOLFSSL="" @@ -51,12 +51,12 @@ if test "x$OPT_WOLFSSL" != xno; then dnl try pkg-config magic CURL_CHECK_PKGCONFIG(wolfssl, [$wolfpkg]) - AC_MSG_NOTICE([Check dir $wolfpkg]) + AC_MSG_NOTICE([Check directory $wolfpkg]) addld="" addlib="" addcflags="" - if test "$PKGCONFIG" != "no" ; then + if test "$PKGCONFIG" != "no"; then addlib=`CURL_EXPORT_PCDIR([$wolfpkg]) $PKGCONFIG --libs-only-l wolfssl` addld=`CURL_EXPORT_PCDIR([$wolfpkg]) @@ -76,13 +76,13 @@ if test "x$OPT_WOLFSSL" != xno; then fi fi - if test "$curl_cv_apple" = 'yes'; then + if test "$curl_cv_apple" = "yes"; then addlib="$addlib -framework Security -framework CoreFoundation" else addlib="$addlib -lm" fi - if test "x$USE_WOLFSSL" != "xyes"; then + if test "$USE_WOLFSSL" != "yes"; then LDFLAGS="$LDFLAGS $addld" LDFLAGSPC="$LDFLAGSPC $addld" @@ -114,7 +114,7 @@ if test "x$OPT_WOLFSSL" != xno; then WOLFSSL_ENABLED=1 USE_WOLFSSL="yes" ssl_msg="wolfSSL" - test wolfssl != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes + test "wolfssl" != "$DEFAULT_SSL_BACKEND" || VALID_DEFAULT_SSL_BACKEND=yes ], [ AC_MSG_RESULT(no) @@ -126,7 +126,7 @@ if test "x$OPT_WOLFSSL" != xno; then LIBS="$my_ac_save_LIBS" fi - if test "x$USE_WOLFSSL" = "xyes"; then + if test "$USE_WOLFSSL" = "yes"; then AC_MSG_NOTICE([detected wolfSSL]) check_for_ca_bundle=1 @@ -150,21 +150,21 @@ if test "x$OPT_WOLFSSL" != xno; then dnl if this symbol is present, we want the include path to include the dnl OpenSSL API root as well - if test "x$ac_cv_func_wolfSSL_DES_ecb_encrypt" = 'xyes'; then + if test "$ac_cv_func_wolfSSL_DES_ecb_encrypt" = "yes"; then HAVE_WOLFSSL_DES_ECB_ENCRYPT=1 fi dnl if this symbol is present, we can make use of BIO filter chains - if test "x$ac_cv_func_wolfSSL_BIO_new" = 'xyes'; then + if test "$ac_cv_func_wolfSSL_BIO_new" = "yes"; then HAVE_WOLFSSL_BIO_NEW=1 fi if test -n "$wolfssllibpath"; then - dnl when shared libs were found in a path that the run-time - dnl linker doesn't search through, we need to add it to + dnl when shared libs were found in a path that the runtime + dnl linker does not search through, we need to add it to dnl CURL_LIBRARY_PATH to prevent further configure tests to fail dnl due to this - if test "x$cross_compiling" != "xyes"; then + if test "$cross_compiling" != "yes"; then CURL_LIBRARY_PATH="$CURL_LIBRARY_PATH:$wolfssllibpath" export CURL_LIBRARY_PATH AC_MSG_NOTICE([Added $wolfssllibpath to CURL_LIBRARY_PATH]) @@ -172,7 +172,7 @@ if test "x$OPT_WOLFSSL" != xno; then fi LIBCURL_PC_REQUIRES_PRIVATE="$LIBCURL_PC_REQUIRES_PRIVATE wolfssl" else - AC_MSG_ERROR([--with-wolfssl but wolfSSL was not found or doesn't work]) + AC_MSG_ERROR([--with-wolfssl but wolfSSL was not found or does not work]) fi fi dnl wolfSSL not disabled diff --git a/m4/xc-lt-iface.m4 b/m4/xc-lt-iface.m4 index a4088003535e..83bf62ccf6cf 100644 --- a/m4/xc-lt-iface.m4 +++ b/m4/xc-lt-iface.m4 @@ -59,8 +59,8 @@ case "x$enable_static" in @%:@ ( xc_lt_want_enable_static='no' ;; esac -if test "x$xc_lt_want_enable_shared" = 'xno' && - test "x$xc_lt_want_enable_static" = 'xno'; then +if test "$xc_lt_want_enable_shared" = "no" && + test "$xc_lt_want_enable_static" = "no"; then AC_MSG_ERROR([can not disable shared and static libraries simultaneously]) fi @@ -71,10 +71,10 @@ fi # must be used in order to build a proper static library. # -if test "x$xc_lt_want_enable_shared" = 'xyes' && - test "x$xc_lt_want_enable_static" = 'xyes'; then +if test "$xc_lt_want_enable_shared" = "yes" && + test "$xc_lt_want_enable_static" = "yes"; then case $host_os in @%:@ ( - cegcc* | os2* | aix*) + os2* | aix*) xc_lt_want_enable_static='no' ;; esac @@ -117,7 +117,7 @@ esac # be overridden using 'configure --disable-shared --without-pic'. # -if test "x$xc_lt_want_with_pic" = 'xdefault'; then +if test "$xc_lt_want_with_pic" = "default"; then case $host_cpu in @%:@ ( x86_64 | amd64 | ia64) case $host_os in @%:@ ( @@ -229,7 +229,7 @@ m4_define([_XC_CHECK_LT_SHLIB_USE_VERSION_INFO], AC_MSG_CHECKING([whether to build shared libraries with -version-info]) xc_lt_shlib_use_version_info='yes' -if test "x$version_type" = 'xnone'; then +if test "$version_type" = "none"; then xc_lt_shlib_use_version_info='no' fi case $host_os in @%:@ ( @@ -259,13 +259,13 @@ m4_define([_XC_CHECK_LT_SHLIB_USE_NO_UNDEFINED], AC_MSG_CHECKING([whether to build shared libraries with -no-undefined]) xc_lt_shlib_use_no_undefined='no' -if test "x$allow_undefined" = 'xno'; then +if test "x$allow_undefined" = "xno"; then xc_lt_shlib_use_no_undefined='yes' -elif test "x$allow_undefined_flag" = 'xunsupported'; then +elif test "x$allow_undefined_flag" = "xunsupported"; then xc_lt_shlib_use_no_undefined='yes' fi case $host_os in @%:@ ( - cygwin* | mingw* | cegcc* | os2* | aix*) + cygwin* | mingw* | os2* | aix*) xc_lt_shlib_use_no_undefined='yes' ;; esac @@ -293,7 +293,7 @@ AC_MSG_CHECKING([whether to build shared libraries with -mimpure-text]) xc_lt_shlib_use_mimpure_text='no' case $host_os in @%:@ ( solaris2*) - if test "x$GCC" = 'xyes'; then + if test "x$GCC" = "xyes"; then xc_lt_shlib_use_mimpure_text='yes' fi ;; @@ -367,8 +367,8 @@ m4_define([_XC_CHECK_LT_BUILD_SINGLE_VERSION], # AC_MSG_CHECKING([whether to build shared libraries only]) -if test "$xc_lt_build_shared" = 'yes' && - test "$xc_lt_build_static" = 'no'; then +if test "$xc_lt_build_shared" = "yes" && + test "$xc_lt_build_static" = "no"; then xc_lt_build_shared_only='yes' else xc_lt_build_shared_only='no' @@ -380,8 +380,8 @@ AC_MSG_RESULT([$xc_lt_build_shared_only]) # AC_MSG_CHECKING([whether to build static libraries only]) -if test "$xc_lt_build_static" = 'yes' && - test "$xc_lt_build_shared" = 'no'; then +if test "$xc_lt_build_static" = "yes" && + test "$xc_lt_build_shared" = "no"; then xc_lt_build_static_only='yes' else xc_lt_build_static_only='no' diff --git a/m4/xc-val-flgs.m4 b/m4/xc-val-flgs.m4 index e2225c2e5742..fd906434966e 100644 --- a/m4/xc-val-flgs.m4 +++ b/m4/xc-val-flgs.m4 @@ -39,7 +39,7 @@ AC_DEFUN([_XC_CHECK_VAR_LIBS], [ ;; esac done - if test $xc_bad_var_libs = yes; then + if test "$xc_bad_var_libs" = "yes"; then AC_MSG_NOTICE([using LIBS: $LIBS]) AC_MSG_NOTICE([LIBS note: LIBS should only be used to specify libraries (-lname).]) fi @@ -68,7 +68,7 @@ AC_DEFUN([_XC_CHECK_VAR_LDFLAGS], [ ;; esac done - if test $xc_bad_var_ldflags = yes; then + if test "$xc_bad_var_ldflags" = "yes"; then AC_MSG_NOTICE([using LDFLAGS: $LDFLAGS]) xc_bad_var_msg="LDFLAGS note: LDFLAGS should only be used to specify linker flags, not" for xc_word in $LDFLAGS; do @@ -110,7 +110,7 @@ AC_DEFUN([_XC_CHECK_VAR_CPPFLAGS], [ ;; esac done - if test $xc_bad_var_cppflags = yes; then + if test "$xc_bad_var_cppflags" = "yes"; then AC_MSG_NOTICE([using CPPFLAGS: $CPPFLAGS]) xc_bad_var_msg="CPPFLAGS note: CPPFLAGS should only be used to specify C preprocessor flags, not" for xc_word in $CPPFLAGS; do @@ -158,7 +158,7 @@ AC_DEFUN([_XC_CHECK_VAR_CFLAGS], [ ;; esac done - if test $xc_bad_var_cflags = yes; then + if test "$xc_bad_var_cflags" = "yes"; then AC_MSG_NOTICE([using CFLAGS: $CFLAGS]) xc_bad_var_msg="CFLAGS note: CFLAGS should only be used to specify C compiler flags, not" for xc_word in $CFLAGS; do @@ -207,10 +207,10 @@ AC_DEFUN([XC_CHECK_USER_FLAGS], [ _XC_CHECK_VAR_LDFLAGS _XC_CHECK_VAR_CPPFLAGS _XC_CHECK_VAR_CFLAGS - if test $xc_bad_var_libs = yes || - test $xc_bad_var_cflags = yes || - test $xc_bad_var_ldflags = yes || - test $xc_bad_var_cppflags = yes; then + if test "$xc_bad_var_libs" = "yes" || + test "$xc_bad_var_cflags" = "yes" || + test "$xc_bad_var_ldflags" = "yes" || + test "$xc_bad_var_cppflags" = "yes"; then AC_MSG_ERROR([Can not continue. Fix errors mentioned immediately above this line.]) fi ]) @@ -226,7 +226,7 @@ dnl script might have set. When checks fails, user dnl is noticed about errors detected in all of them dnl but script continues execution. dnl -dnl Intended to be used very late in configure script. +dnl Intended to be used late in configure script. AC_DEFUN([XC_CHECK_BUILD_FLAGS], [ AC_PREREQ([2.50])dnl @@ -235,10 +235,10 @@ AC_DEFUN([XC_CHECK_BUILD_FLAGS], [ _XC_CHECK_VAR_LDFLAGS _XC_CHECK_VAR_CPPFLAGS _XC_CHECK_VAR_CFLAGS - if test $xc_bad_var_libs = yes || - test $xc_bad_var_cflags = yes || - test $xc_bad_var_ldflags = yes || - test $xc_bad_var_cppflags = yes; then + if test "$xc_bad_var_libs" = "yes" || + test "$xc_bad_var_cflags" = "yes" || + test "$xc_bad_var_ldflags" = "yes" || + test "$xc_bad_var_cppflags" = "yes"; then AC_MSG_WARN([Continuing even with errors mentioned immediately above this line.]) fi ]) diff --git a/m4/zz40-xc-ovr.m4 b/m4/zz40-xc-ovr.m4 index 6faa94e43ee2..02c86c9eeaad 100644 --- a/m4/zz40-xc-ovr.m4 +++ b/m4/zz40-xc-ovr.m4 @@ -393,7 +393,7 @@ done IFS=$xc_tst_prev_IFS xc_tst_dirs_sem=`expr "$xc_tst_dirs_sem" : '.*'` -if test $xc_tst_dirs_sem -eq $xc_tst_dirs_col; then +if test "$xc_tst_dirs_sem" -eq "$xc_tst_dirs_col"; then # When both counting methods give the same result we do not want to # chose one over the other, and consider auto-detection not possible. if test -z "$PATH_SEPARATOR"; then @@ -404,7 +404,7 @@ if test $xc_tst_dirs_sem -eq $xc_tst_dirs_col; then fi else # Separator with the greater directory count is the auto-detected one. - if test $xc_tst_dirs_sem -gt $xc_tst_dirs_col; then + if test "$xc_tst_dirs_sem" -gt "$xc_tst_dirs_col"; then xc_tst_auto_separator=';' else xc_tst_auto_separator=':' @@ -448,7 +448,7 @@ dnl ------------------------------------------------- dnl Public macro. dnl dnl This macro emits shell code which does some -dnl very basic checks related with the availability +dnl basic checks related with the availability dnl of some commands and utilities needed to allow dnl configure script bootstrapping itself when using dnl these to figure out other settings. Also emits @@ -602,7 +602,7 @@ dnl overrides the auto-detected one. dnl dnl Strictly speaking the check is done in two steps. The dnl first, which does the actual check, takes place in -dnl XC_CONFIGURE_PREAMBLE macro and happens very early in +dnl XC_CONFIGURE_PREAMBLE macro and happens early in dnl generated configure script. The second one shows and dnl logs the result of the check into config.log at a later dnl configure stage. Placement of this second stage in diff --git a/m4/zz50-xc-ovr.m4 b/m4/zz50-xc-ovr.m4 index 735df2f59b69..1a1e4a017766 100644 --- a/m4/zz50-xc-ovr.m4 +++ b/m4/zz50-xc-ovr.m4 @@ -35,7 +35,7 @@ dnl ------------------------------------------------- dnl This is done to prevent Libtool 1.5.X from doing dnl unnecessary C++, Fortran and Java tests when only dnl using C language and reduce resulting configure -dnl script by nearly 300 Kb. +dnl script by nearly 300 KB. m4_ifdef([AC_LIBTOOL_LANG_CXX_CONFIG], [m4_undefine([AC_LIBTOOL_LANG_CXX_CONFIG])]) diff --git a/m4/zz60-xc-ovr.m4 b/m4/zz60-xc-ovr.m4 deleted file mode 100644 index d1d3a2fd50f9..000000000000 --- a/m4/zz60-xc-ovr.m4 +++ /dev/null @@ -1,65 +0,0 @@ -#--------------------------------------------------------------------------- -# -# zz60-xc-ovr.m4 -# -# Copyright (C) Daniel Stenberg, -# -# Permission to use, copy, modify, and distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -# -# SPDX-License-Identifier: ISC -# -#--------------------------------------------------------------------------- - -# serial 1 - - -dnl The funny name of this file is intentional in order to make it -dnl sort alphabetically after any libtool, autoconf or automake -dnl provided .m4 macro file that might get copied into this same -dnl subdirectory. This allows that macro (re)definitions from this -dnl file may override those provided in other files. - - -dnl Override an autoconf provided macro -dnl ------------------------------------------------- -dnl This macro overrides the one provided by autoconf -dnl 2.58 or newer, and provides macro definition for -dnl autoconf 2.57 or older which lack it. This allows -dnl using libtool 2.2 or newer, which requires that -dnl this macro is used in configure.ac, with autoconf -dnl 2.57 or older. - -m4_ifdef([AC_CONFIG_MACRO_DIR], -[dnl -m4_undefine([AC_CONFIG_MACRO_DIR])dnl -]) -m4_define([AC_CONFIG_MACRO_DIR],[]) - - -dnl XC_OVR_ZZ60 -dnl ------------------------------------------------- -dnl Placing a call to this macro in configure.ac will -dnl make macros in this file visible to other macros -dnl used for same configure script, overriding those -dnl provided elsewhere. - -AC_DEFUN([XC_OVR_ZZ60], -[dnl -AC_BEFORE([$0],[LT_INIT])dnl -AC_BEFORE([$0],[AM_INIT_AUTOMAKE])dnl -AC_BEFORE([$0],[AC_LIBTOOL_WIN32_DLL])dnl -AC_BEFORE([$0],[AC_PROG_LIBTOOL])dnl -dnl -AC_BEFORE([$0],[AC_CONFIG_MACRO_DIR])dnl -AC_BEFORE([$0],[AC_CONFIG_MACRO_DIRS])dnl -]) diff --git a/packages/Makefile.am b/packages/Makefile.am index 43e544a0195c..8b6d4dc4b242 100644 --- a/packages/Makefile.am +++ b/packages/Makefile.am @@ -24,6 +24,7 @@ SUBDIRS = vms EXTRA_DIST = README.md \ + OS400/.checksrc \ OS400/README.OS400 \ OS400/rpg-examples \ OS400/ccsidcurl.c \ diff --git a/packages/OS400/.checksrc b/packages/OS400/.checksrc new file mode 100644 index 000000000000..3bd88ff1e7db --- /dev/null +++ b/packages/OS400/.checksrc @@ -0,0 +1,9 @@ +# Copyright (C) Daniel Stenberg, , et al. +# +# SPDX-License-Identifier: curl + +# Possibly not what we want, but cannot test, just silence the warnings +allowfunc calloc +allowfunc free +allowfunc malloc +allowfunc realloc diff --git a/packages/OS400/ccsidcurl.c b/packages/OS400/ccsidcurl.c index b40367fd960b..0982eed639f7 100644 --- a/packages/OS400/ccsidcurl.c +++ b/packages/OS400/ccsidcurl.c @@ -46,20 +46,17 @@ #include "os400sys.h" #ifndef SIZE_MAX -#define SIZE_MAX ((size_t) ~0) /* Is unsigned on OS/400. */ +#define SIZE_MAX ((size_t)~0) /* Is unsigned on OS/400. */ #endif +#define ASCII_CCSID 819 /* Use ISO-8859-1 as ASCII. */ +#define NOCONV_CCSID 65535 /* No conversion. */ +#define ICONV_ID_SIZE 32 /* Size of iconv_open() code identifier. */ +#define ICONV_OPEN_ERROR(t) ((t).return_value == -1) -#define ASCII_CCSID 819 /* Use ISO-8859-1 as ASCII. */ -#define NOCONV_CCSID 65535 /* No conversion. */ -#define ICONV_ID_SIZE 32 /* Size of iconv_open() code identifier. */ -#define ICONV_OPEN_ERROR(t) ((t).return_value == -1) +#define ALLOC_GRANULE 8 /* Alloc. granule for curl_formadd_ccsid(). */ -#define ALLOC_GRANULE 8 /* Alloc. granule for curl_formadd_ccsid(). */ - - -static void -makeOS400IconvCode(char buf[ICONV_ID_SIZE], unsigned int ccsid) +static void makeOS400IconvCode(char buf[ICONV_ID_SIZE], unsigned int ccsid) { /** *** Convert a CCSID to the corresponding IBM iconv_open() character @@ -78,10 +75,8 @@ makeOS400IconvCode(char buf[ICONV_ID_SIZE], unsigned int ccsid) curl_msprintf(buf, "IBMCCSID%05u0000000", ccsid); } - -static iconv_t -iconv_open_CCSID(unsigned int ccsidout, unsigned int ccsidin, - unsigned int cstr) +static iconv_t iconv_open_CCSID(unsigned int ccsidout, unsigned int ccsidin, + unsigned int cstr) { char fromcode[ICONV_ID_SIZE]; char tocode[ICONV_ID_SIZE]; @@ -95,18 +90,16 @@ iconv_open_CCSID(unsigned int ccsidout, unsigned int ccsidin, makeOS400IconvCode(fromcode, ccsidin); makeOS400IconvCode(tocode, ccsidout); - memset(tocode + 13, 0, sizeof(tocode) - 13); /* Dest. code id format. */ + memset(tocode + 13, 0, sizeof(tocode) - 13); /* Dest. code id format. */ if(cstr) - fromcode[18] = '1'; /* Set null-terminator flag. */ + fromcode[18] = '1'; /* Set null-terminator flag. */ return iconv_open(tocode, fromcode); } - -static int -convert(char *d, size_t dlen, int dccsid, - const char *s, int slen, int sccsid) +static int convert(char *d, size_t dlen, int dccsid, const char *s, int slen, + int sccsid) { int i; iconv_t cd; @@ -134,23 +127,23 @@ convert(char *d, size_t dlen, int dccsid, memcpy(d, s, i); return i; - } + } if(slen < 0) { lslen = 0; cd = iconv_open_CCSID(dccsid, sccsid, 1); - } + } else { - lslen = (size_t) slen; + lslen = (size_t)slen; cd = iconv_open_CCSID(dccsid, sccsid, 0); - } + } if(ICONV_OPEN_ERROR(cd)) return -1; i = dlen; - if((int) iconv(cd, (char * *) &s, &lslen, &d, &dlen) < 0) + if((int)iconv(cd, (char **)&s, &lslen, &d, &dlen) < 0) i = -1; else i -= dlen; @@ -159,8 +152,8 @@ convert(char *d, size_t dlen, int dccsid, return i; } - -static char *dynconvert(int dccsid, const char *s, int slen, int sccsid) +static char *dynconvert(int dccsid, const char *s, int slen, int sccsid, + int *olen) { char *d; char *cp; @@ -170,19 +163,19 @@ static char *dynconvert(int dccsid, const char *s, int slen, int sccsid) /* Like convert, but the destination is allocated and returned. */ - dlen = (size_t) (slen < 0 ? strlen(s) : slen) + 1; - dlen *= MAX_CONV_EXPANSION; /* Allow some expansion. */ + dlen = (size_t)(slen < 0 ? strlen(s) : slen) + 1; + dlen *= MAX_CONV_EXPANSION; /* Allow some expansion. */ d = malloc(dlen); if(!d) - return (char *) NULL; + return (char *)NULL; l = convert(d, dlen, dccsid, s, slen, sccsid); if(l < 0) { free(d); - return (char *) NULL; - } + return (char *)NULL; + } if(slen < 0) { /* Need to null-terminate even when source length is given. @@ -193,35 +186,36 @@ static char *dynconvert(int dccsid, const char *s, int slen, int sccsid) if(l2 < 0) { free(d); - return (char *) NULL; - } + return (char *)NULL; + } l += l2; - } + } - if((size_t) l < dlen) { - cp = realloc(d, l); /* Shorten to minimum needed. */ + if((size_t)l < dlen) { + cp = realloc(d, l); /* Shorten to minimum needed. */ if(cp) d = cp; - } + } + if(olen) + *olen = l; return d; } - -static struct curl_slist * -slist_convert(int dccsid, struct curl_slist *from, int sccsid) +static struct curl_slist *slist_convert(int dccsid, struct curl_slist *from, + int sccsid) { - struct curl_slist *to = (struct curl_slist *) NULL; + struct curl_slist *to = (struct curl_slist *)NULL; for(; from; from = from->next) { struct curl_slist *nl; - char *cp = dynconvert(dccsid, from->data, -1, sccsid); + char *cp = dynconvert(dccsid, from->data, -1, sccsid, NULL); if(!cp) { curl_slist_free_all(to); - return (struct curl_slist *) NULL; + return (struct curl_slist *)NULL; } nl = Curl_slist_append_nodup(to, cp); if(!nl) { @@ -234,15 +228,14 @@ slist_convert(int dccsid, struct curl_slist *from, int sccsid) return to; } - -static char * -keyed_string(localkey_t key, const char *ascii, unsigned int ccsid) +static char *keyed_string(localkey_t key, const char *ascii, + unsigned int ccsid) { int i; char *ebcdic; if(!ascii) - return (char *) NULL; + return (char *)NULL; i = MAX_CONV_EXPANSION * (strlen(ascii) + 1); @@ -251,40 +244,32 @@ keyed_string(localkey_t key, const char *ascii, unsigned int ccsid) return ebcdic; if(convert(ebcdic, i, ccsid, ascii, -1, ASCII_CCSID) < 0) - return (char *) NULL; + return (char *)NULL; return ebcdic; } - -const char * -curl_to_ccsid(const char *s, unsigned int ccsid) +const char *curl_to_ccsid(const char *s, unsigned int ccsid) { if(s) - s = dynconvert(ccsid, s, -1, ASCII_CCSID); + s = dynconvert(ccsid, s, -1, ASCII_CCSID, NULL); return s; } - -const char * -curl_from_ccsid(const char *s, unsigned int ccsid) +const char *curl_from_ccsid(const char *s, unsigned int ccsid) { if(s) - s = dynconvert(ASCII_CCSID, s, -1, ccsid); + s = dynconvert(ASCII_CCSID, s, -1, ccsid, NULL); return s; } - -char * -curl_version_ccsid(unsigned int ccsid) +char *curl_version_ccsid(unsigned int ccsid) { return keyed_string(LK_CURL_VERSION, curl_version(), ccsid); } - -char * -curl_easy_escape_ccsid(CURL *handle, const char *string, int length, - unsigned int sccsid, unsigned int dccsid) +char *curl_easy_escape_ccsid(CURL *handle, const char *string, int length, + unsigned int sccsid, unsigned int dccsid) { char *s; char *d; @@ -292,30 +277,28 @@ curl_easy_escape_ccsid(CURL *handle, const char *string, int length, if(!string) { /* !checksrc! disable ERRNOVAR 1 */ errno = EINVAL; - return (char *) NULL; - } + return (char *)NULL; + } - s = dynconvert(ASCII_CCSID, string, length ? length : -1, sccsid); + s = dynconvert(ASCII_CCSID, string, length ? length : -1, sccsid, NULL); if(!s) - return (char *) NULL; + return (char *)NULL; d = curl_easy_escape(handle, s, 0); free(s); if(!d) - return (char *) NULL; + return (char *)NULL; - s = dynconvert(dccsid, d, -1, ASCII_CCSID); + s = dynconvert(dccsid, d, -1, ASCII_CCSID, NULL); free(d); return s; } - -char * -curl_easy_unescape_ccsid(CURL *handle, const char *string, int length, - int *outlength, - unsigned int sccsid, unsigned int dccsid) +char *curl_easy_unescape_ccsid(CURL *handle, const char *string, int length, + int *outlength, unsigned int sccsid, + unsigned int dccsid) { char *s; char *d; @@ -323,21 +306,21 @@ curl_easy_unescape_ccsid(CURL *handle, const char *string, int length, if(!string) { /* !checksrc! disable ERRNOVAR 1 */ errno = EINVAL; - return (char *) NULL; - } + return (char *)NULL; + } - s = dynconvert(ASCII_CCSID, string, length ? length : -1, sccsid); + s = dynconvert(ASCII_CCSID, string, length ? length : -1, sccsid, NULL); if(!s) - return (char *) NULL; + return (char *)NULL; d = curl_easy_unescape(handle, s, 0, outlength); free(s); if(!d) - return (char *) NULL; + return (char *)NULL; - s = dynconvert(dccsid, d, -1, ASCII_CCSID); + s = dynconvert(dccsid, d, -1, ASCII_CCSID, NULL); free(d); if(s && outlength) @@ -346,31 +329,29 @@ curl_easy_unescape_ccsid(CURL *handle, const char *string, int length, return s; } - -struct curl_slist * -curl_slist_append_ccsid(struct curl_slist *list, - const char *data, unsigned int ccsid) +struct curl_slist *curl_slist_append_ccsid(struct curl_slist *list, + const char *data, + unsigned int ccsid) { char *s; - s = (char *) NULL; + s = (char *)NULL; if(!data) return curl_slist_append(list, data); - s = dynconvert(ASCII_CCSID, data, -1, ccsid); + s = dynconvert(ASCII_CCSID, data, -1, ccsid, NULL); if(!s) - return (struct curl_slist *) NULL; + return (struct curl_slist *)NULL; list = curl_slist_append(list, s); free(s); return list; } - -time_t -curl_getdate_ccsid(const char *p, const time_t *unused, unsigned int ccsid) +time_t curl_getdate_ccsid(const char *p, const time_t *unused, + unsigned int ccsid) { char *s; time_t t; @@ -378,20 +359,18 @@ curl_getdate_ccsid(const char *p, const time_t *unused, unsigned int ccsid) if(!p) return curl_getdate(p, unused); - s = dynconvert(ASCII_CCSID, p, -1, ccsid); + s = dynconvert(ASCII_CCSID, p, -1, ccsid, NULL); if(!s) - return (time_t) -1; + return (time_t)-1; t = curl_getdate(s, unused); free(s); return t; } - -static int -convert_version_info_string(const char **stringp, - char **bufp, int *left, unsigned int ccsid) +static int convert_version_info_string(const char **stringp, char **bufp, + int *left, unsigned int ccsid) { /* Helper for curl_version_info_ccsid(): convert a string if defined. Result is stored in the `*left'-byte buffer at `*bufp'. @@ -407,14 +386,13 @@ convert_version_info_string(const char **stringp, *stringp = *bufp; *bufp += l; *left -= l; - } + } return 0; } - -curl_version_info_data * -curl_version_info_ccsid(CURLversion stamp, unsigned int ccsid) +curl_version_info_data *curl_version_info_ccsid(CURLversion stamp, + unsigned int ccsid) { curl_version_info_data *p; char *cp; @@ -454,7 +432,7 @@ curl_version_info_ccsid(CURLversion stamp, unsigned int ccsid) /* If caller has been compiled with a newer version, error. */ if(stamp > CURLVERSION_NOW) - return (curl_version_info_data *) NULL; + return (curl_version_info_data *)NULL; p = curl_version_info(stamp); @@ -471,10 +449,10 @@ curl_version_info_ccsid(CURLversion stamp, unsigned int ccsid) n += strlen(p->protocols[nproto++]); n += nproto++; - } + } for(i = 0; i < sizeof(charfields) / sizeof(charfields[0]); i++) { - cpp = (const char **) ((char *) p + charfields[i]); + cpp = (const char **)((char *)p + charfields[i]); if(*cpp) n += strlen(*cpp) + 1; } @@ -487,70 +465,60 @@ curl_version_info_ccsid(CURLversion stamp, unsigned int ccsid) n += nproto * sizeof(const char *); cp = Curl_thread_buffer(LK_VERSION_INFO_DATA, n); - id = (curl_version_info_data *) Curl_thread_buffer(LK_VERSION_INFO, - sizeof(*id)); + id = (curl_version_info_data *)Curl_thread_buffer(LK_VERSION_INFO, + sizeof(*id)); if(!id || !cp) - return (curl_version_info_data *) NULL; + return (curl_version_info_data *)NULL; /* Copy data and convert strings. */ - memcpy((char *) id, (char *) p, sizeof(*p)); + memcpy((char *)id, (char *)p, sizeof(*p)); if(id->protocols) { i = nproto * sizeof(id->protocols[0]); - id->protocols = (const char * const *) cp; - memcpy(cp, (char *) p->protocols, i); + id->protocols = (const char * const *)cp; + memcpy(cp, (char *)p->protocols, i); cp += i; n -= i; for(i = 0; id->protocols[i]; i++) - if(convert_version_info_string(((const char * *) id->protocols) + i, - &cp, &n, ccsid)) - return (curl_version_info_data *) NULL; + if(convert_version_info_string(((const char **)id->protocols) + i, + &cp, &n, ccsid)) + return (curl_version_info_data *)NULL; } for(i = 0; i < sizeof(charfields) / sizeof(charfields[0]); i++) { - cpp = (const char **) ((char *) p + charfields[i]); + cpp = (const char **)((char *)p + charfields[i]); if(*cpp && convert_version_info_string(cpp, &cp, &n, ccsid)) - return (curl_version_info_data *) NULL; + return (curl_version_info_data *)NULL; } return id; } - -const char * -curl_easy_strerror_ccsid(CURLcode error, unsigned int ccsid) +const char *curl_easy_strerror_ccsid(CURLcode error, unsigned int ccsid) { return keyed_string(LK_EASY_STRERROR, curl_easy_strerror(error), ccsid); } - -const char * -curl_share_strerror_ccsid(CURLSHcode error, unsigned int ccsid) +const char *curl_share_strerror_ccsid(CURLSHcode error, unsigned int ccsid) { return keyed_string(LK_SHARE_STRERROR, curl_share_strerror(error), ccsid); } - -const char * -curl_multi_strerror_ccsid(CURLMcode error, unsigned int ccsid) +const char *curl_multi_strerror_ccsid(CURLMcode error, unsigned int ccsid) { return keyed_string(LK_MULTI_STRERROR, curl_multi_strerror(error), ccsid); } - -const char * -curl_url_strerror_ccsid(CURLUcode error, unsigned int ccsid) +const char *curl_url_strerror_ccsid(CURLUcode error, unsigned int ccsid) { return keyed_string(LK_URL_STRERROR, curl_url_strerror(error), ccsid); } - -void -curl_certinfo_free_all(struct curl_certinfo *info) +void curl_certinfo_free_all(struct curl_certinfo *info) { /* Free all memory used by certificate info. */ if(info) { @@ -559,15 +527,13 @@ curl_certinfo_free_all(struct curl_certinfo *info) for(i = 0; i < info->num_of_certs; i++) curl_slist_free_all(info->certinfo[i]); - free((char *) info->certinfo); + free((char *)info->certinfo); } - free((char *) info); + free((char *)info); } } - -CURLcode -curl_easy_getinfo_ccsid(CURL *curl, CURLINFO info, ...) +CURLcode curl_easy_getinfo_ccsid(CURL *curl, CURLINFO info, ...) { va_list arg; void *paramp; @@ -577,7 +543,7 @@ curl_easy_getinfo_ccsid(CURL *curl, CURLINFO info, ...) /* WARNING: unlike curl_easy_getinfo(), the strings returned by this procedure have to be free'ed. */ - data = (struct Curl_easy *) curl; + data = (struct Curl_easy *)curl; va_start(arg, info); paramp = va_arg(arg, void *); ret = Curl_getinfo(data, info, paramp); @@ -589,14 +555,14 @@ curl_easy_getinfo_ccsid(CURL *curl, CURLINFO info, ...) struct curl_certinfo *cipf; struct curl_certinfo *cipt; - switch((int) info & CURLINFO_TYPEMASK) { + switch((int)info & CURLINFO_TYPEMASK) { case CURLINFO_STRING: ccsid = va_arg(arg, unsigned int); - cpp = (char * *) paramp; + cpp = (char **)paramp; if(*cpp) { - *cpp = dynconvert(ccsid, *cpp, -1, ASCII_CCSID); + *cpp = dynconvert(ccsid, *cpp, -1, ASCII_CCSID, NULL); if(!*cpp) ret = CURLE_OUT_OF_MEMORY; @@ -608,15 +574,15 @@ curl_easy_getinfo_ccsid(CURL *curl, CURLINFO info, ...) ccsid = va_arg(arg, unsigned int); switch(info) { case CURLINFO_CERTINFO: - cipf = *(struct curl_certinfo * *) paramp; + cipf = *(struct curl_certinfo **)paramp; if(cipf) { - cipt = (struct curl_certinfo *) malloc(sizeof(*cipt)); + cipt = (struct curl_certinfo *)malloc(sizeof(*cipt)); if(!cipt) ret = CURLE_OUT_OF_MEMORY; else { - cipt->certinfo = (struct curl_slist **) - calloc(cipf->num_of_certs + - 1, sizeof(struct curl_slist *)); + cipt->certinfo = + (struct curl_slist **)calloc(cipf->num_of_certs + 1, + sizeof(struct curl_slist *)); if(!cipt->certinfo) ret = CURLE_OUT_OF_MEMORY; else { @@ -626,20 +592,20 @@ curl_easy_getinfo_ccsid(CURL *curl, CURLINFO info, ...) for(i = 0; i < cipf->num_of_certs; i++) if(cipf->certinfo[i]) if(!(cipt->certinfo[i] = slist_convert(ccsid, - cipf->certinfo[i], - ASCII_CCSID))) { + cipf->certinfo[i], + ASCII_CCSID))) { ret = CURLE_OUT_OF_MEMORY; break; } - } } + } if(ret != CURLE_OK) { curl_certinfo_free_all(cipt); - cipt = (struct curl_certinfo *) NULL; + cipt = (struct curl_certinfo *)NULL; } - *(struct curl_certinfo * *) paramp = cipt; + *(struct curl_certinfo **)paramp = cipt; } break; @@ -650,7 +616,7 @@ curl_easy_getinfo_ccsid(CURL *curl, CURLINFO info, ...) break; default: - slp = (struct curl_slist **) paramp; + slp = (struct curl_slist **)paramp; if(*slp) { *slp = slist_convert(ccsid, *slp, ASCII_CCSID); if(!*slp) @@ -665,9 +631,7 @@ curl_easy_getinfo_ccsid(CURL *curl, CURLINFO info, ...) return ret; } - -static int -Curl_is_formadd_string(CURLformoption option) +static int Curl_is_formadd_string(CURLformoption option) { switch(option) { @@ -684,23 +648,20 @@ Curl_is_formadd_string(CURLformoption option) return 0; } - -static void -Curl_formadd_release_local(struct curl_forms *forms, int nargs, int skip) +static void Curl_formadd_release_local(struct curl_forms *forms, int nargs, + int skip) { while(nargs--) if(nargs != skip) if(Curl_is_formadd_string(forms[nargs].option)) if(forms[nargs].value) - free((char *) forms[nargs].value); + free((char *)forms[nargs].value); - free((char *) forms); + free((char *)forms); } - -static int -Curl_formadd_convert(struct curl_forms *forms, - int formx, int lengthx, unsigned int ccsid) +static int Curl_formadd_convert(struct curl_forms *forms, int formx, + int lengthx, unsigned int ccsid) { int l; char *cp; @@ -710,7 +671,7 @@ Curl_formadd_convert(struct curl_forms *forms, return 0; if(lengthx >= 0) - l = (int) forms[lengthx].value; + l = (int)forms[lengthx].value; else l = strlen(forms[formx].value) + 1; @@ -719,15 +680,15 @@ Curl_formadd_convert(struct curl_forms *forms, if(!cp) return -1; - l = convert(cp, MAX_CONV_EXPANSION * l, ASCII_CCSID, - forms[formx].value, l, ccsid); + l = convert(cp, MAX_CONV_EXPANSION * l, ASCII_CCSID, forms[formx].value, l, + ccsid); if(l < 0) { free(cp); return -1; - } + } - cp2 = realloc(cp, l); /* Shorten buffer to the string size. */ + cp2 = realloc(cp, l); /* Shorten buffer to the string size. */ if(cp2) cp = cp2; @@ -735,15 +696,13 @@ Curl_formadd_convert(struct curl_forms *forms, forms[formx].value = cp; if(lengthx >= 0) - forms[lengthx].value = (char *) l; /* Update length after conversion. */ + forms[lengthx].value = (char *)l; /* Update length after conversion. */ return l; } - -CURLFORMcode -curl_formadd_ccsid(struct curl_httppost **httppost, - struct curl_httppost **last_post, ...) +CURLFORMcode curl_formadd_ccsid(struct curl_httppost **httppost, + struct curl_httppost **last_post, ...) { va_list arg; CURLformoption option; @@ -794,7 +753,7 @@ curl_formadd_ccsid(struct curl_httppost **httppost, lengthx = -1; namex = -1; namelengthx = -1; - forms = (struct curl_forms *) NULL; + forms = (struct curl_forms *)NULL; va_start(arg, last_post); for(;;) { @@ -807,10 +766,10 @@ curl_formadd_ccsid(struct curl_httppost **httppost, if(!tforms) { result = CURL_FORMADD_MEMORY; break; - } + } lforms = tforms; - } + } /* Get next option. */ @@ -820,7 +779,7 @@ curl_formadd_ccsid(struct curl_httppost **httppost, option = forms->option; value = forms->value; forms++; - } + } else { /* Get option from arguments. */ @@ -828,27 +787,27 @@ curl_formadd_ccsid(struct curl_httppost **httppost, if(option == CURLFORM_END) break; - } + } /* Dispatch by option. */ switch(option) { case CURLFORM_END: - forms = (struct curl_forms *) NULL; /* Leave array mode. */ + forms = (struct curl_forms *)NULL; /* Leave array mode. */ continue; case CURLFORM_ARRAY: if(!forms) { forms = va_arg(arg, struct curl_forms *); continue; - } + } result = CURL_FORMADD_ILLEGAL_ARRAY; break; case CURLFORM_COPYNAME: - option = CURLFORM_PTRNAME; /* Static for now. */ + option = CURLFORM_PTRNAME; /* Static for now. */ case CURLFORM_PTRNAME: if(namex >= 0) @@ -858,12 +817,12 @@ curl_formadd_ccsid(struct curl_httppost **httppost, if(!forms) { value = va_arg(arg, char *); - nameccsid = (unsigned int) va_arg(arg, long); - } + nameccsid = (unsigned int)va_arg(arg, long); + } else { - nameccsid = (unsigned int) forms->value; + nameccsid = (unsigned int)forms->value; forms++; - } + } break; @@ -875,19 +834,19 @@ curl_formadd_ccsid(struct curl_httppost **httppost, if(!forms) { value = va_arg(arg, char *); - contentccsid = (unsigned int) va_arg(arg, long); - } + contentccsid = (unsigned int)va_arg(arg, long); + } else { - contentccsid = (unsigned int) forms->value; + contentccsid = (unsigned int)forms->value; forms++; - } + } break; case CURLFORM_PTRCONTENTS: case CURLFORM_BUFFERPTR: if(!forms) - value = va_arg(arg, char *); /* No conversion. */ + value = va_arg(arg, char *); /* No conversion. */ break; @@ -895,7 +854,7 @@ curl_formadd_ccsid(struct curl_httppost **httppost, lengthx = nargs; if(!forms) - value = (char *) va_arg(arg, long); + value = (char *)va_arg(arg, long); break; @@ -903,7 +862,7 @@ curl_formadd_ccsid(struct curl_httppost **httppost, lengthx = nargs; if(!forms) - value = (char *) va_arg(arg, curl_off_t); + value = (char *)va_arg(arg, curl_off_t); break; @@ -911,25 +870,25 @@ curl_formadd_ccsid(struct curl_httppost **httppost, namelengthx = nargs; if(!forms) - value = (char *) va_arg(arg, long); + value = (char *)va_arg(arg, long); break; case CURLFORM_BUFFERLENGTH: if(!forms) - value = (char *) va_arg(arg, long); + value = (char *)va_arg(arg, long); break; case CURLFORM_CONTENTHEADER: if(!forms) - value = (char *) va_arg(arg, struct curl_slist *); + value = (char *)va_arg(arg, struct curl_slist *); break; case CURLFORM_STREAM: if(!forms) - value = (char *) va_arg(arg, void *); + value = (char *)va_arg(arg, void *); break; @@ -939,7 +898,7 @@ curl_formadd_ccsid(struct curl_httppost **httppost, if(Curl_formadd_convert(lforms, contentx, lengthx, contentccsid) < 0) { result = CURL_FORMADD_MEMORY; break; - } + } contentx = -1; lengthx = -1; @@ -951,16 +910,16 @@ curl_formadd_ccsid(struct curl_httppost **httppost, if(!Curl_is_formadd_string(option)) { result = CURL_FORMADD_UNKNOWN_OPTION; break; - } + } if(!forms) { value = va_arg(arg, char *); - ccsid = (unsigned int) va_arg(arg, long); - } + ccsid = (unsigned int)va_arg(arg, long); + } else { - ccsid = (unsigned int) forms->value; + ccsid = (unsigned int)forms->value; forms++; - } + } /* Do the conversion. */ @@ -969,17 +928,17 @@ curl_formadd_ccsid(struct curl_httppost **httppost, if(Curl_formadd_convert(lforms, nargs, -1, ccsid) < 0) { result = CURL_FORMADD_MEMORY; break; - } + } value = lforms[nargs].value; - } + } if(result != CURL_FORMADD_OK) break; lforms[nargs].value = value; lforms[nargs++].option = option; - } + } va_end(arg); @@ -989,15 +948,15 @@ curl_formadd_ccsid(struct curl_httppost **httppost, if(Curl_formadd_convert(lforms, namex, namelengthx, nameccsid) < 0) result = CURL_FORMADD_MEMORY; else - lforms[namex].option = CURLFORM_COPYNAME; /* Force copy. */ - } + lforms[namex].option = CURLFORM_COPYNAME; /* Force copy. */ + } if(result == CURL_FORMADD_OK) { if(Curl_formadd_convert(lforms, contentx, lengthx, contentccsid) < 0) result = CURL_FORMADD_MEMORY; else contentx = -1; - } + } /* Do the formadd with our converted parameters. */ @@ -1005,7 +964,7 @@ curl_formadd_ccsid(struct curl_httppost **httppost, lforms[nargs].option = CURLFORM_END; result = curl_formadd(httppost, last_post, CURLFORM_ARRAY, lforms, CURLFORM_END); - } + } /* Terminate. */ @@ -1013,60 +972,54 @@ curl_formadd_ccsid(struct curl_httppost **httppost, return result; } - struct cfcdata { curl_formget_callback append; void * arg; unsigned int ccsid; }; - -static size_t -Curl_formget_callback_ccsid(void *arg, const char *buf, size_t len) +static size_t Curl_formget_callback_ccsid(void *arg, const char *buf, + size_t len) { struct cfcdata *p; char *b; int l; size_t ret; - p = (struct cfcdata *) arg; + p = (struct cfcdata *)arg; - if((long) len <= 0) + if((long)len <= 0) return (*p->append)(p->arg, buf, len); b = malloc(MAX_CONV_EXPANSION * len); if(!b) - return (size_t) -1; + return (size_t)-1; l = convert(b, MAX_CONV_EXPANSION * len, p->ccsid, buf, len, ASCII_CCSID); if(l < 0) { free(b); - return (size_t) -1; - } + return (size_t)-1; + } ret = (*p->append)(p->arg, b, l); free(b); return ret == l ? len : -1; } - -int -curl_formget_ccsid(struct curl_httppost *form, void *arg, - curl_formget_callback append, unsigned int ccsid) +int curl_formget_ccsid(struct curl_httppost *form, void *arg, + curl_formget_callback append, unsigned int ccsid) { struct cfcdata lcfc; lcfc.append = append; lcfc.arg = arg; lcfc.ccsid = ccsid; - return curl_formget(form, (void *) &lcfc, Curl_formget_callback_ccsid); + return curl_formget(form, (void *)&lcfc, Curl_formget_callback_ccsid); } - -CURLcode -curl_easy_setopt_ccsid(CURL *easy, CURLoption tag, ...) +CURLcode curl_easy_setopt_ccsid(CURL *easy, CURLoption tag, ...) { CURLcode result; va_list arg; @@ -1180,7 +1133,7 @@ curl_easy_setopt_ccsid(CURL *easy, CURLoption tag, ...) ccsid = va_arg(arg, unsigned int); if(s) { - s = dynconvert(ASCII_CCSID, s, -1, ccsid); + s = dynconvert(ASCII_CCSID, s, -1, ccsid, NULL); if(!s) { result = CURLE_OUT_OF_MEMORY; @@ -1208,7 +1161,7 @@ curl_easy_setopt_ccsid(CURL *easy, CURLoption tag, ...) if(pfsize == -1) { /* Data is null-terminated. */ - s = dynconvert(ASCII_CCSID, s, -1, ccsid); + s = dynconvert(ASCII_CCSID, s, -1, ccsid, NULL); if(!s) { result = CURLE_OUT_OF_MEMORY; @@ -1244,13 +1197,13 @@ curl_easy_setopt_ccsid(CURL *easy, CURLoption tag, ...) break; } - data->set.postfieldsize = pfsize; /* Replace data size. */ + data->set.postfieldsize = pfsize; /* Replace data size. */ s = cp; cp = NULL; } result = curl_easy_setopt(easy, CURLOPT_POSTFIELDS, s); - data->set.str[STRING_COPYPOSTFIELDS] = s; /* Give to library. */ + data->set.str[STRING_COPYPOSTFIELDS] = s; /* Give to library. */ break; default: @@ -1262,7 +1215,7 @@ curl_easy_setopt_ccsid(CURL *easy, CURLoption tag, ...) if(bp && bp->data && bp->len && ccsid != NOCONV_CCSID && ccsid != ASCII_CCSID) { - pfsize = (curl_off_t) bp->len * MAX_CONV_EXPANSION; + pfsize = (curl_off_t)bp->len * MAX_CONV_EXPANSION; if(pfsize > SIZE_MAX) pfsize = SIZE_MAX; @@ -1286,11 +1239,11 @@ curl_easy_setopt_ccsid(CURL *easy, CURLoption tag, ...) blob.flags = bp->flags | CURL_BLOB_COPY; bp = &blob; } - result = curl_easy_setopt(easy, tag, &blob); + result = curl_easy_setopt(easy, tag, bp); break; } FALLTHROUGH(); - case CURLOPT_ERRORBUFFER: /* This is an output buffer. */ + case CURLOPT_ERRORBUFFER: /* This is an output buffer. */ result = Curl_vsetopt(easy, tag, arg); break; } @@ -1300,70 +1253,62 @@ curl_easy_setopt_ccsid(CURL *easy, CURLoption tag, ...) return result; } - /* ILE/RPG helper functions. */ -char * -curl_form_long_value(long value) +char *curl_form_long_value(long value) { /* ILE/RPG cannot cast an integer to a pointer. This procedure does it. */ - return (char *) value; + return (char *)value; } - -CURLcode -curl_easy_setopt_RPGnum_(CURL *easy, CURLoption tag, curl_off_t arg) +CURLcode curl_easy_setopt_RPGnum_(CURL *easy, CURLoption tag, curl_off_t arg) { /* ILE/RPG procedure overloading cannot discriminate between different size and/or signedness of format arguments. This provides a generic wrapper that adapts size to the given tag expectation. This procedure is not intended to be explicitly called from user code. */ if(tag / 10000 != CURLOPTTYPE_OFF_T) - return curl_easy_setopt(easy, tag, (long) arg); + return curl_easy_setopt(easy, tag, (long)arg); return curl_easy_setopt(easy, tag, arg); } - -CURLcode -curl_multi_setopt_RPGnum_(CURLM *multi, CURLMoption tag, curl_off_t arg) +CURLcode curl_multi_setopt_RPGnum_(CURLM *multi, CURLMoption tag, + curl_off_t arg) { /* Likewise, for multi handle. */ if(tag / 10000 != CURLOPTTYPE_OFF_T) - return curl_multi_setopt(multi, tag, (long) arg); + return curl_multi_setopt(multi, tag, (long)arg); return curl_multi_setopt(multi, tag, arg); } - -char * -curl_pushheader_bynum_cssid(struct curl_pushheaders *h, - size_t num, unsigned int ccsid) +char *curl_pushheader_bynum_cssid(struct curl_pushheaders *h, size_t num, + unsigned int ccsid) { - char *d = (char *) NULL; + char *d = (char *)NULL; char *s = curl_pushheader_bynum(h, num); if(s) - d = dynconvert(ccsid, s, -1, ASCII_CCSID); + d = dynconvert(ccsid, s, -1, ASCII_CCSID, NULL); return d; } - -char * -curl_pushheader_byname_ccsid(struct curl_pushheaders *h, const char *header, - unsigned int ccsidin, unsigned int ccsidout) +char *curl_pushheader_byname_ccsid(struct curl_pushheaders *h, + const char *header, unsigned int ccsidin, + unsigned int ccsidout) { - char *d = (char *) NULL; + char *d = (char *)NULL; if(header) { - header = dynconvert(ASCII_CCSID, header, -1, ccsidin); + header = dynconvert(ASCII_CCSID, header, -1, ccsidin, NULL); if(header) { char *s = curl_pushheader_byname(h, header); - free((char *) header); + free((char *)header); if(s) - d = dynconvert(ccsidout, s, -1, ASCII_CCSID); + d = dynconvert(ccsidout, s, -1, ASCII_CCSID, NULL); } } @@ -1374,12 +1319,12 @@ static CURLcode mime_string_call(curl_mimepart *part, const char *string, unsigned int ccsid, CURLcode (*mimefunc)(curl_mimepart *part, const char *string)) { - char *s = (char *) NULL; + char *s = (char *)NULL; CURLcode result; if(!string) return mimefunc(part, string); - s = dynconvert(ASCII_CCSID, string, -1, ccsid); + s = dynconvert(ASCII_CCSID, string, -1, ccsid, NULL); if(!s) return CURLE_OUT_OF_MEMORY; @@ -1388,61 +1333,56 @@ mime_string_call(curl_mimepart *part, const char *string, unsigned int ccsid, return result; } -CURLcode -curl_mime_name_ccsid(curl_mimepart *part, const char *name, unsigned int ccsid) +CURLcode curl_mime_name_ccsid(curl_mimepart *part, const char *name, + unsigned int ccsid) { return mime_string_call(part, name, ccsid, curl_mime_name); } -CURLcode -curl_mime_filename_ccsid(curl_mimepart *part, - const char *filename, unsigned int ccsid) +CURLcode curl_mime_filename_ccsid(curl_mimepart *part, const char *filename, + unsigned int ccsid) { return mime_string_call(part, filename, ccsid, curl_mime_filename); } -CURLcode -curl_mime_type_ccsid(curl_mimepart *part, - const char *mimetype, unsigned int ccsid) +CURLcode curl_mime_type_ccsid(curl_mimepart *part, const char *mimetype, + unsigned int ccsid) { return mime_string_call(part, mimetype, ccsid, curl_mime_type); } -CURLcode -curl_mime_encoder_ccsid(curl_mimepart *part, - const char *encoding, unsigned int ccsid) +CURLcode curl_mime_encoder_ccsid(curl_mimepart *part, const char *encoding, + unsigned int ccsid) { return mime_string_call(part, encoding, ccsid, curl_mime_encoder); } -CURLcode -curl_mime_filedata_ccsid(curl_mimepart *part, - const char *filename, unsigned int ccsid) +CURLcode curl_mime_filedata_ccsid(curl_mimepart *part, const char *filename, + unsigned int ccsid) { return mime_string_call(part, filename, ccsid, curl_mime_filedata); } -CURLcode -curl_mime_data_ccsid(curl_mimepart *part, - const char *data, size_t datasize, unsigned int ccsid) +CURLcode curl_mime_data_ccsid(curl_mimepart *part, const char *data, + size_t datasize, unsigned int ccsid) { - char *s = (char *) NULL; + char *s = (char *)NULL; CURLcode result; + int osize; if(!data) return curl_mime_data(part, data, datasize); - s = dynconvert(ASCII_CCSID, data, datasize, ccsid); + s = dynconvert(ASCII_CCSID, data, datasize, ccsid, &osize); if(!s) return CURLE_OUT_OF_MEMORY; - result = curl_mime_data(part, s, datasize); + result = curl_mime_data(part, s, osize); free(s); return result; } -CURLUcode -curl_url_get_ccsid(CURLU *handle, CURLUPart what, char **part, - unsigned int flags, unsigned int ccsid) +CURLUcode curl_url_get_ccsid(CURLU *handle, CURLUPart what, char **part, + unsigned int flags, unsigned int ccsid) { char *s = (char *)NULL; CURLUcode result; @@ -1454,7 +1394,7 @@ curl_url_get_ccsid(CURLU *handle, CURLUPart what, char **part, result = curl_url_get(handle, what, &s, flags); if(result == CURLUE_OK) { if(s) { - *part = dynconvert(ccsid, s, -1, ASCII_CCSID); + *part = dynconvert(ccsid, s, -1, ASCII_CCSID, NULL); if(!*part) result = CURLUE_OUT_OF_MEMORY; } @@ -1464,15 +1404,14 @@ curl_url_get_ccsid(CURLU *handle, CURLUPart what, char **part, return result; } -CURLUcode -curl_url_set_ccsid(CURLU *handle, CURLUPart what, const char *part, - unsigned int flags, unsigned int ccsid) +CURLUcode curl_url_set_ccsid(CURLU *handle, CURLUPart what, const char *part, + unsigned int flags, unsigned int ccsid) { char *s = (char *)NULL; CURLUcode result; if(part) { - s = dynconvert(ASCII_CCSID, part, -1, ccsid); + s = dynconvert(ASCII_CCSID, part, -1, ccsid, NULL); if(!s) return CURLUE_OUT_OF_MEMORY; } @@ -1488,7 +1427,7 @@ curl_easy_option_by_name_ccsid(const char *name, unsigned int ccsid) const struct curl_easyoption *option = NULL; if(name) { - char *s = dynconvert(ASCII_CCSID, name, -1, ccsid); + char *s = dynconvert(ASCII_CCSID, name, -1, ccsid, NULL); if(s) { option = curl_easy_option_by_name(s); @@ -1507,21 +1446,20 @@ curl_easy_option_get_name_ccsid(const struct curl_easyoption *option, char *name = NULL; if(option && option->name) - name = dynconvert(ccsid, option->name, -1, ASCII_CCSID); + name = dynconvert(ccsid, option->name, -1, ASCII_CCSID, NULL); - return (const char *) name; + return (const char *)name; } /* Header API CCSID support. */ -CURLHcode -curl_easy_header_ccsid(CURL *easy, const char *name, size_t index, - unsigned int origin, int request, - struct curl_header **hout, unsigned int ccsid) +CURLHcode curl_easy_header_ccsid(CURL *easy, const char *name, size_t index, + unsigned int origin, int request, + struct curl_header **hout, unsigned int ccsid) { CURLHcode result = CURLHE_BAD_ARGUMENT; if(name) { - char *s = dynconvert(ASCII_CCSID, name, -1, ccsid); + char *s = dynconvert(ASCII_CCSID, name, -1, ccsid, NULL); result = CURLHE_OUT_OF_MEMORY; if(s) { diff --git a/packages/OS400/ccsidcurl.h b/packages/OS400/ccsidcurl.h index ab01d32b854b..f9e667a9e41c 100644 --- a/packages/OS400/ccsidcurl.h +++ b/packages/OS400/ccsidcurl.h @@ -28,7 +28,6 @@ #include "easy.h" #include "multi.h" - CURL_EXTERN char *curl_version_ccsid(unsigned int ccsid); CURL_EXTERN char *curl_easy_escape_ccsid(CURL *handle, const char *string, int length, diff --git a/packages/OS400/curl.cmd b/packages/OS400/curl.cmd index 822f4db207e6..fa6aaa59a568 100644 --- a/packages/OS400/curl.cmd +++ b/packages/OS400/curl.cmd @@ -29,4 +29,4 @@ PARM KWD(CMDARGS) TYPE(*CHAR) LEN(5000) VARY(*YES *INT2) + CASE(*MIXED) EXPR(*YES) MIN(1) + - PROMPT('Curl command arguments') + PROMPT('curl command arguments') diff --git a/packages/OS400/curlcl.c b/packages/OS400/curlcl.c index ca497b351d43..7a7f3c6459d6 100644 --- a/packages/OS400/curlcl.c +++ b/packages/OS400/curlcl.c @@ -48,16 +48,13 @@ struct arguments { struct vary2 *cmdargs; /* Command line arguments. */ }; -static int -is_ifs(char c) +static int is_ifs(char c) { return c == ' ' || c == '\t' || c == '\r' || c == '\n'; } -static int -parse_command_line(const char *cmdargs, size_t len, - size_t *argc, char **argv, - size_t *argsize, char *argbuf) +static int parse_command_line(const char *cmdargs, size_t len, size_t *argc, + char **argv, size_t *argsize, char *argbuf) { const char *endline = cmdargs + len; char quote = '\0'; @@ -126,9 +123,7 @@ parse_command_line(const char *cmdargs, size_t len, return 0; } - -int -main(int argsc, struct arguments *args) +int main(int argsc, struct arguments *args) { size_t argc; char **argv; @@ -154,20 +149,20 @@ main(int argsc, struct arguments *args) if(!exitcode) { /* Allocate space for parsed arguments. */ - argv = (char **) malloc((argc + 1) * sizeof(*argv) + argsize); + argv = (char **)malloc((argc + 1) * sizeof(*argv) + argsize); if(!argv) { fputs("Memory allocation error\n", stderr); exitcode = -2; } else { - _SYSPTR pgmptr = rslvsp(WLI_PGM, (char *) CURLPGM, library, _AUTH_NONE); - _LU_Work_Area_T *luwrka = (_LU_Work_Area_T *) _LUWRKA(); + _SYSPTR pgmptr = rslvsp(WLI_PGM, (char *)CURLPGM, library, _AUTH_NONE); + _LU_Work_Area_T *luwrka = (_LU_Work_Area_T *)_LUWRKA(); - parse_command_line(args->cmdargs->string, args->cmdargs->len, - &argc, argv, &argsize, (char *) (argv + argc + 1)); + parse_command_line(args->cmdargs->string, args->cmdargs->len, &argc, + argv, &argsize, (char *)(argv + argc + 1)); /* Call program. */ - _CALLPGMV((void *) &pgmptr, argv, argc); + _CALLPGMV((void *)&pgmptr, argv, argc); exitcode = luwrka->LU_RC; free(argv); diff --git a/packages/OS400/curlmain.c b/packages/OS400/curlmain.c index 079b9b0d9dcd..54ca865264dd 100644 --- a/packages/OS400/curlmain.c +++ b/packages/OS400/curlmain.c @@ -41,15 +41,13 @@ extern int QadrtFreeConversionTable(void); extern int QadrtFreeEnviron(void); extern char * setlocale_a(int, const char *); - /* The ASCII main program. */ -extern int main_a(int argc, char * * argv); +extern int main_a(int argc, char **argv); /* Global values of original EBCDIC arguments. */ int ebcdic_argc; char ** ebcdic_argv; - int main(int argc, char **argv) { int i; @@ -63,8 +61,8 @@ int main(int argc, char **argv) char dummybuf[128]; /* To/From codes are 32 byte long strings with reserved fields initialized to ZEROs */ - const char tocode[32] = {"IBMCCSID01208"}; /* Use UTF-8. */ - const char fromcode[32] = {"IBMCCSID000000000010"}; + const char tocode[32] = { "IBMCCSID01208" }; /* Use UTF-8. */ + const char fromcode[32] = { "IBMCCSID000000000010" }; ebcdic_argc = argc; ebcdic_argv = argv; @@ -85,13 +83,13 @@ int main(int argc, char **argv) /* Reset the shift state. */ iconv(cd, NULL, &inbytesleft, &outbuf, &outbytesleft); - } + } /* Allocate memory for the ASCII arguments and vector. */ - argv = (char **) malloc((argc + 1) * sizeof(*argv) + bytecount); + argv = (char **)malloc((argc + 1) * sizeof(*argv) + bytecount); /* Build the vector and convert argument encoding. */ - outbuf = (char *) (argv + argc + 1); + outbuf = (char *)(argv + argc + 1); outbytesleft = bytecount; for(i = 0; i < argc; i++) { @@ -112,7 +110,7 @@ int main(int argc, char **argv) i = main_a(argc, argv); /* Clean-up allocated items. */ - free((char *) argv); + free((char *)argv); QadrtFreeConversionTable(); QadrtFreeEnviron(); diff --git a/packages/OS400/make-lib.sh b/packages/OS400/make-lib.sh index e7b5b519e7e8..cd3f71897f2d 100755 --- a/packages/OS400/make-lib.sh +++ b/packages/OS400/make-lib.sh @@ -79,7 +79,7 @@ fi if [ -n "${LINK}" ] then rm -rf "${LIBIFSNAME}/${STATBNDDIR}.BNDDIR" CMD="CRTBNDDIR BNDDIR(${TARGETLIB}/${STATBNDDIR})" - CMD="${CMD} TEXT('LibCurl API static binding directory')" + CMD="${CMD} TEXT('libcurl API static binding directory')" CLcommand "${CMD}" for MODULE in ${MODULES} @@ -173,7 +173,7 @@ fi if [ -n "${LINK}" ] then rm -rf "${LIBIFSNAME}/${DYNBNDDIR}.BNDDIR" CMD="CRTBNDDIR BNDDIR(${TARGETLIB}/${DYNBNDDIR})" - CMD="${CMD} TEXT('LibCurl API dynamic binding directory')" + CMD="${CMD} TEXT('libcurl API dynamic binding directory')" CLcommand "${CMD}" CMD="ADDBNDDIRE BNDDIR(${TARGETLIB}/${DYNBNDDIR})" CMD="${CMD} OBJ((*LIBL/${SRVPGM} *SRVPGM))" diff --git a/packages/OS400/make-tests.sh b/packages/OS400/make-tests.sh index 3a2125965cfc..4ddc537487b2 100755 --- a/packages/OS400/make-tests.sh +++ b/packages/OS400/make-tests.sh @@ -58,7 +58,7 @@ build_all_programs() for FLAG in ${PGMCFLAGS} do case "${FLAG}" in - -D?*) # shellcheck disable=SC2001 + -D?*) DEFINE="$(echo "${FLAG}" | sed 's/^..//')" PGMDFNS="${PGMDFNS} '${DEFINE}'" ;; diff --git a/packages/OS400/makefile.sh b/packages/OS400/makefile.sh index 7f7584521589..2b688a4421d4 100755 --- a/packages/OS400/makefile.sh +++ b/packages/OS400/makefile.sh @@ -35,8 +35,10 @@ cd "${TOPDIR}" || exit 1 # Make sure all files are UTF8-encoded. +# Qshell does not support -print0. ls -S has a non-POSIX meaning. +# https://www.ibm.com/docs/en/i/7.1.0?topic=qshell-command-language # shellcheck disable=SC2038 -find "${TOPDIR}" -type f -print | xargs ls -S | while read -r CCSID FILE +find "${TOPDIR}" -type f | xargs ls -S -- | while read -r CCSID FILE do if [ "${CCSID}" != 1208 ] then CMD="CPY OBJ('${FILE}') TOOBJ('${FILE}') FROMCCSID(*OBJ)" CMD="${CMD} TOCCSID(1208) DTAFMT(*TEXT) REPLACE(*YES)" @@ -65,7 +67,7 @@ fi # Copy some documentation files if needed. for TEXT in "${TOPDIR}/COPYING" "${SCRIPTDIR}/README.OS400" \ - "${TOPDIR}/CHANGES.md" "${TOPDIR}/docs/THANKS" "${TOPDIR}/docs/FAQ" \ + "${TOPDIR}/CHANGES.md" "${TOPDIR}/docs/THANKS" "${TOPDIR}/docs/FAQ.md" \ "${TOPDIR}/docs/FEATURES" "${TOPDIR}/docs/SSLCERTS.md" \ "${TOPDIR}/docs/RESOURCES" "${TOPDIR}/docs/VERSIONS.md" \ "${TOPDIR}/docs/HISTORY.md" diff --git a/packages/OS400/os400sys.c b/packages/OS400/os400sys.c index 40eca6edc290..04be163617a8 100644 --- a/packages/OS400/os400sys.c +++ b/packages/OS400/os400sys.c @@ -65,14 +65,13 @@ #pragma convert(0) /* Restore EBCDIC. */ -#define MIN_BYTE_GAIN 1024 /* Minimum gain when shortening a buffer. */ +#define MIN_BYTE_GAIN 1024 /* Minimum gain when shortening a buffer. */ struct buffer_t { unsigned long size; /* Buffer size. */ char *buf; /* Buffer address. */ }; - static char *buffer_undef(localkey_t key, long size); static char *buffer_threaded(localkey_t key, long size); static char *buffer_unthreaded(localkey_t key, long size); @@ -86,10 +85,10 @@ char *(*Curl_thread_buffer)(localkey_t key, long size) = buffer_undef; static void thdbufdestroy(void *private) { if(private) { - struct buffer_t *p = (struct buffer_t *) private; + struct buffer_t *p = (struct buffer_t *)private; localkey_t i; - for(i = (localkey_t) 0; i < LK_LAST; i++) { + for(i = (localkey_t)0; i < LK_LAST; i++) { free(p->buf); p++; } @@ -98,27 +97,23 @@ static void thdbufdestroy(void *private) } } - -static void -terminate(void) +static void terminate(void) { if(Curl_thread_buffer == buffer_threaded) { locbufs = pthread_getspecific(thdkey); - pthread_setspecific(thdkey, (void *) NULL); + pthread_setspecific(thdkey, (void *)NULL); pthread_key_delete(thdkey); } if(Curl_thread_buffer != buffer_undef) { - thdbufdestroy((void *) locbufs); - locbufs = (struct buffer_t *) NULL; + thdbufdestroy((void *)locbufs); + locbufs = (struct buffer_t *)NULL; } Curl_thread_buffer = buffer_undef; } - -static char * -get_buffer(struct buffer_t *buf, long size) +static char *get_buffer(struct buffer_t *buf, long size) { char *cp; @@ -136,7 +131,7 @@ get_buffer(struct buffer_t *buf, long size) return buf->buf; } - if((unsigned long) size <= buf->size) { + if((unsigned long)size <= buf->size) { /* Shorten the buffer only if it frees a significant byte count. This avoids some realloc() overhead. */ @@ -157,27 +152,23 @@ get_buffer(struct buffer_t *buf, long size) return cp; } - /* * Get buffer address for the given local key. * This is always called though `Curl_thread_buffer' and when threads are * NOT made available by the os, so no mutex lock/unlock occurs. */ -static char * -buffer_unthreaded(localkey_t key, long size) +static char *buffer_unthreaded(localkey_t key, long size) { return get_buffer(locbufs + key, size); } - /* * Get buffer address for the given local key, taking care of * concurrent threads. * This is always called though `Curl_thread_buffer' and when threads are * made available by the os. */ -static char * -buffer_threaded(localkey_t key, long size) +static char *buffer_threaded(localkey_t key, long size) { struct buffer_t *bufs; @@ -185,30 +176,28 @@ buffer_threaded(localkey_t key, long size) make sure it is at least `size'-byte long. Set `size' to < 0 to get its address only. */ - bufs = (struct buffer_t *) pthread_getspecific(thdkey); + bufs = (struct buffer_t *)pthread_getspecific(thdkey); if(!bufs) { if(size < 0) - return (char *) NULL; /* No buffer yet. */ + return (char *)NULL; /* No buffer yet. */ /* Allocate buffer descriptors for the current thread. */ - bufs = calloc((size_t) LK_LAST, sizeof(*bufs)); + bufs = calloc((size_t)LK_LAST, sizeof(*bufs)); if(!bufs) - return (char *) NULL; + return (char *)NULL; - if(pthread_setspecific(thdkey, (void *) bufs)) { + if(pthread_setspecific(thdkey, (void *)bufs)) { free(bufs); - return (char *) NULL; + return (char *)NULL; } } return get_buffer(bufs + key, size); } - -static char * -buffer_undef(localkey_t key, long size) +static char *buffer_undef(localkey_t key, long size) { /* Define the buffer system, get the buffer for the given local key in the current thread, and make sure it is at least `size'-byte long. @@ -218,7 +207,7 @@ buffer_undef(localkey_t key, long size) /* Determine if we can use pthread-specific data. */ - if(Curl_thread_buffer == buffer_undef) { /* If unchanged during lock. */ + if(Curl_thread_buffer == buffer_undef) { /* If unchanged during lock. */ /* OS400 interactive jobs do not support threads: check here. */ if(!pthread_key_create(&thdkey, thdbufdestroy)) { /* Threads are supported: use the thread-aware buffer procedure. */ @@ -227,10 +216,10 @@ buffer_undef(localkey_t key, long size) else { /* No multi-threading available: allocate storage for single-thread * buffer headers. */ - locbufs = calloc((size_t) LK_LAST, sizeof(*locbufs)); + locbufs = calloc((size_t)LK_LAST, sizeof(*locbufs)); if(!locbufs) { - pthread_mutex_unlock(&mutex); /* For symetry: will probably fail. */ - return (char *) NULL; + pthread_mutex_unlock(&mutex); /* For symetry: will probably fail. */ + return (char *)NULL; } else Curl_thread_buffer = buffer_unthreaded; /* Use unthreaded version. */ @@ -243,15 +232,13 @@ buffer_undef(localkey_t key, long size) return Curl_thread_buffer(key, size); } - -static char * -set_thread_string(localkey_t key, const char *s) +static char *set_thread_string(localkey_t key, const char *s) { int i; char *cp; if(!s) - return (char *) NULL; + return (char *)NULL; i = strlen(s) + 1; cp = Curl_thread_buffer(key, MAX_CONV_EXPANSION * i + 1); @@ -264,12 +251,10 @@ set_thread_string(localkey_t key, const char *s) return cp; } - -int -Curl_getnameinfo_a(const struct sockaddr *sa, socklen_t salen, - char *nodename, socklen_t nodenamelen, - char *servname, socklen_t servnamelen, - int flags) +int Curl_getnameinfo_a(const struct sockaddr *sa, socklen_t salen, + char *nodename, socklen_t nodenamelen, + char *servname, socklen_t servnamelen, + int flags) { char *enodename = NULL; char *eservname = NULL; @@ -289,20 +274,20 @@ Curl_getnameinfo_a(const struct sockaddr *sa, socklen_t salen, } } - status = getnameinfo(sa, salen, enodename, nodenamelen, - eservname, servnamelen, flags); + status = getnameinfo(sa, salen, enodename, nodenamelen, eservname, + servnamelen, flags); if(!status) { int i; if(enodename) { - i = QadrtConvertE2A(nodename, enodename, - nodenamelen - 1, strlen(enodename)); + i = QadrtConvertE2A(nodename, enodename, nodenamelen - 1, + strlen(enodename)); nodename[i] = '\0'; } if(eservname) { - i = QadrtConvertE2A(servname, eservname, - servnamelen - 1, strlen(eservname)); + i = QadrtConvertE2A(servname, eservname, servnamelen - 1, + strlen(eservname)); servname[i] = '\0'; } } @@ -312,18 +297,16 @@ Curl_getnameinfo_a(const struct sockaddr *sa, socklen_t salen, return status; } -int -Curl_getaddrinfo_a(const char *nodename, const char *servname, - const struct addrinfo *hints, - struct addrinfo **res) +int Curl_getaddrinfo_a(const char *nodename, const char *servname, + const struct addrinfo *hints, struct addrinfo **res) { char *enodename; char *eservname; int status; int i; - enodename = (char *) NULL; - eservname = (char *) NULL; + enodename = (char *)NULL; + eservname = (char *)NULL; if(nodename) { i = strlen(nodename); @@ -360,8 +343,7 @@ Curl_getaddrinfo_a(const char *nodename, const char *servname, /* ASCII wrappers for the GSSAPI procedures. */ -static int -Curl_gss_convert_in_place(OM_uint32 *minor_status, gss_buffer_t buf) +static int Curl_gss_convert_in_place(OM_uint32 *minor_status, gss_buffer_t buf) { unsigned int i = buf->length; @@ -388,10 +370,8 @@ Curl_gss_convert_in_place(OM_uint32 *minor_status, gss_buffer_t buf) return 0; } - -OM_uint32 -Curl_gss_import_name_a(OM_uint32 *minor_status, gss_buffer_t in_name, - gss_OID in_name_type, gss_name_t *out_name) +OM_uint32 Curl_gss_import_name_a(OM_uint32 *minor_status, gss_buffer_t in_name, + gss_OID in_name_type, gss_name_t *out_name) { OM_uint32 rc; unsigned int i; @@ -400,7 +380,7 @@ Curl_gss_import_name_a(OM_uint32 *minor_status, gss_buffer_t in_name, if(!in_name || !in_name->value || !in_name->length) return gss_import_name(minor_status, in_name, in_name_type, out_name); - memcpy((char *) &in, (char *) in_name, sizeof(in)); + memcpy((char *)&in, (char *)in_name, sizeof(in)); i = in.length; in.value = malloc(i + 1); @@ -413,17 +393,17 @@ Curl_gss_import_name_a(OM_uint32 *minor_status, gss_buffer_t in_name, } QadrtConvertA2E(in.value, in_name->value, i, i); - ((char *) in.value)[i] = '\0'; + ((char *)in.value)[i] = '\0'; rc = gss_import_name(minor_status, &in, in_name_type, out_name); free(in.value); return rc; } -OM_uint32 -Curl_gss_display_status_a(OM_uint32 *minor_status, OM_uint32 status_value, - int status_type, gss_OID mech_type, - gss_msg_ctx_t *message_context, - gss_buffer_t status_string) +OM_uint32 Curl_gss_display_status_a(OM_uint32 *minor_status, + OM_uint32 status_value, int status_type, + gss_OID mech_type, + gss_msg_ctx_t *message_context, + gss_buffer_t status_string) { int rc; @@ -477,7 +457,7 @@ Curl_gss_init_sec_context_a(OM_uint32 *minor_status, } QadrtConvertA2E(in.value, input_token->value, i, i); - ((char *) in.value)[i] = '\0'; + ((char *)in.value)[i] = '\0'; in.length = i; inp = ∈ } @@ -503,11 +483,9 @@ Curl_gss_init_sec_context_a(OM_uint32 *minor_status, return rc; } - -OM_uint32 -Curl_gss_delete_sec_context_a(OM_uint32 *minor_status, - gss_ctx_id_t *context_handle, - gss_buffer_t output_token) +OM_uint32 Curl_gss_delete_sec_context_a(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_buffer_t output_token) { OM_uint32 rc; @@ -533,38 +511,36 @@ Curl_gss_delete_sec_context_a(OM_uint32 *minor_status, /* ASCII wrappers for the LDAP procedures. */ -void * -Curl_ldap_init_a(char *host, int port) +void *Curl_ldap_init_a(char *host, int port) { size_t i; char *ehost; void *result; if(!host) - return (void *) ldap_init(host, port); + return (void *)ldap_init(host, port); i = strlen(host); ehost = malloc(i + 1); if(!ehost) - return (void *) NULL; + return (void *)NULL; QadrtConvertA2E(ehost, host, i, i); ehost[i] = '\0'; - result = (void *) ldap_init(ehost, port); + result = (void *)ldap_init(ehost, port); free(ehost); return result; } -int -Curl_ldap_simple_bind_s_a(void *ld, char *dn, char *passwd) +int Curl_ldap_simple_bind_s_a(void *ld, char *dn, char *passwd) { int i; char *edn; char *epasswd; - edn = (char *) NULL; - epasswd = (char *) NULL; + edn = (char *)NULL; + epasswd = (char *)NULL; if(dn) { i = strlen(dn); @@ -596,9 +572,8 @@ Curl_ldap_simple_bind_s_a(void *ld, char *dn, char *passwd) return i; } -int -Curl_ldap_search_s_a(void *ld, char *base, int scope, char *filter, - char **attrs, int attrsonly, LDAPMessage **res) +int Curl_ldap_search_s_a(void *ld, char *base, int scope, char *filter, + char **attrs, int attrsonly, LDAPMessage **res) { int i; int j; @@ -607,9 +582,9 @@ Curl_ldap_search_s_a(void *ld, char *base, int scope, char *filter, char **eattrs; int status; - ebase = (char *) NULL; - efilter = (char *) NULL; - eattrs = (char **) NULL; + ebase = (char *)NULL; + efilter = (char *)NULL; + eattrs = (char **)NULL; status = LDAP_SUCCESS; if(base) { @@ -676,14 +651,13 @@ Curl_ldap_search_s_a(void *ld, char *base, int scope, char *filter, return status; } - -struct berval ** -Curl_ldap_get_values_len_a(void *ld, LDAPMessage *entry, const char *attr) +struct berval **Curl_ldap_get_values_len_a(void *ld, LDAPMessage *entry, + const char *attr) { char *cp; struct berval **result; - cp = (char *) NULL; + cp = (char *)NULL; if(attr) { int i = strlen(attr); @@ -692,7 +666,7 @@ Curl_ldap_get_values_len_a(void *ld, LDAPMessage *entry, const char *attr) if(!cp) { ldap_set_lderrno(ld, LDAP_NO_MEMORY, NULL, ldap_err2string(LDAP_NO_MEMORY)); - return (struct berval **) NULL; + return (struct berval **)NULL; } QadrtConvertA2E(cp, attr, i, i); @@ -702,20 +676,18 @@ Curl_ldap_get_values_len_a(void *ld, LDAPMessage *entry, const char *attr) result = ldap_get_values_len(ld, entry, cp); free(cp); - /* Result data are binary in nature, so they haven't been + /* Result data are binary in nature, so they have not been converted to EBCDIC. Therefore do not convert. */ return result; } -char * -Curl_ldap_err2string_a(int error) +char *Curl_ldap_err2string_a(int error) { return set_thread_string(LK_LDAP_ERROR, ldap_err2string(error)); } -char * -Curl_ldap_get_dn_a(void *ld, LDAPMessage *entry) +char *Curl_ldap_get_dn_a(void *ld, LDAPMessage *entry) { int i; char *cp; @@ -744,9 +716,8 @@ Curl_ldap_get_dn_a(void *ld, LDAPMessage *entry) return cp; } -char * -Curl_ldap_first_attribute_a(void *ld, - LDAPMessage *entry, BerElement **berptr) +char *Curl_ldap_first_attribute_a(void *ld, LDAPMessage *entry, + BerElement **berptr) { int i; char *cp; @@ -775,9 +746,8 @@ Curl_ldap_first_attribute_a(void *ld, return cp; } -char * -Curl_ldap_next_attribute_a(void *ld, - LDAPMessage *entry, BerElement *berptr) +char *Curl_ldap_next_attribute_a(void *ld, LDAPMessage *entry, + BerElement *berptr) { int i; char *cp; @@ -808,9 +778,8 @@ Curl_ldap_next_attribute_a(void *ld, #endif /* CURL_DISABLE_LDAP */ -static int -sockaddr2ebcdic(struct sockaddr_storage *dstaddr, - const struct sockaddr *srcaddr, int srclen) +static int sockaddr2ebcdic(struct sockaddr_storage *dstaddr, + const struct sockaddr *srcaddr, int srclen) { const struct sockaddr_un *srcu; struct sockaddr_un *dstu; @@ -826,13 +795,13 @@ sockaddr2ebcdic(struct sockaddr_storage *dstaddr, return -1; } - memcpy((char *) dstaddr, (char *) srcaddr, srclen); + memcpy((char *)dstaddr, (char *)srcaddr, srclen); switch(srcaddr->sa_family) { case AF_UNIX: - srcu = (const struct sockaddr_un *) srcaddr; - dstu = (struct sockaddr_un *) dstaddr; + srcu = (const struct sockaddr_un *)srcaddr; + dstu = (struct sockaddr_un *)dstaddr; dstsize = sizeof(*dstaddr) - offsetof(struct sockaddr_un, sun_path); srclen -= offsetof(struct sockaddr_un, sun_path); i = QadrtConvertA2E(dstu->sun_path, srcu->sun_path, dstsize - 1, srclen); @@ -843,10 +812,8 @@ sockaddr2ebcdic(struct sockaddr_storage *dstaddr, return srclen; } - -static int -sockaddr2ascii(struct sockaddr *dstaddr, int dstlen, - const struct sockaddr_storage *srcaddr, int srclen) +static int sockaddr2ascii(struct sockaddr *dstaddr, int dstlen, + const struct sockaddr_storage *srcaddr, int srclen) { const struct sockaddr_un *srcu; struct sockaddr_un *dstu; @@ -864,15 +831,15 @@ sockaddr2ascii(struct sockaddr *dstaddr, int dstlen, return -1; } - memcpy((char *) dstaddr, (char *) srcaddr, srclen); + memcpy((char *)dstaddr, (char *)srcaddr, srclen); if(srclen >= offsetof(struct sockaddr_storage, ss_family) + sizeof(srcaddr->ss_family)) { switch(srcaddr->ss_family) { case AF_UNIX: - srcu = (const struct sockaddr_un *) srcaddr; - dstu = (struct sockaddr_un *) dstaddr; + srcu = (const struct sockaddr_un *)srcaddr; + dstu = (struct sockaddr_un *)dstaddr; dstsize = dstlen - offsetof(struct sockaddr_un, sun_path); srclen -= offsetof(struct sockaddr_un, sun_path); if(dstsize > 0 && srclen > 0) { @@ -887,8 +854,7 @@ sockaddr2ascii(struct sockaddr *dstaddr, int dstlen, return srclen; } -int -Curl_os400_connect(int sd, struct sockaddr *destaddr, int addrlen) +int Curl_os400_connect(int sd, struct sockaddr *destaddr, int addrlen) { int i; struct sockaddr_storage laddr; @@ -898,11 +864,10 @@ Curl_os400_connect(int sd, struct sockaddr *destaddr, int addrlen) if(i < 0) return -1; - return connect(sd, (struct sockaddr *) &laddr, i); + return connect(sd, (struct sockaddr *)&laddr, i); } -int -Curl_os400_bind(int sd, struct sockaddr *localaddr, int addrlen) +int Curl_os400_bind(int sd, struct sockaddr *localaddr, int addrlen) { int i; struct sockaddr_storage laddr; @@ -912,12 +877,11 @@ Curl_os400_bind(int sd, struct sockaddr *localaddr, int addrlen) if(i < 0) return -1; - return bind(sd, (struct sockaddr *) &laddr, i); + return bind(sd, (struct sockaddr *)&laddr, i); } -int -Curl_os400_sendto(int sd, char *buffer, int buflen, int flags, - const struct sockaddr *dstaddr, int addrlen) +int Curl_os400_sendto(int sd, char *buffer, int buflen, int flags, + const struct sockaddr *dstaddr, int addrlen) { int i; struct sockaddr_storage laddr; @@ -927,12 +891,11 @@ Curl_os400_sendto(int sd, char *buffer, int buflen, int flags, if(i < 0) return -1; - return sendto(sd, buffer, buflen, flags, (struct sockaddr *) &laddr, i); + return sendto(sd, buffer, buflen, flags, (struct sockaddr *)&laddr, i); } -int -Curl_os400_recvfrom(int sd, char *buffer, int buflen, int flags, - struct sockaddr *fromaddr, int *addrlen) +int Curl_os400_recvfrom(int sd, char *buffer, int buflen, int flags, + struct sockaddr *fromaddr, int *addrlen) { int rcvlen; struct sockaddr_storage laddr; @@ -943,7 +906,7 @@ Curl_os400_recvfrom(int sd, char *buffer, int buflen, int flags, laddr.ss_family = AF_UNSPEC; /* To detect if unused. */ rcvlen = recvfrom(sd, buffer, buflen, flags, - (struct sockaddr *) &laddr, &laddrlen); + (struct sockaddr *)&laddr, &laddrlen); if(rcvlen < 0) return rcvlen; @@ -959,12 +922,11 @@ Curl_os400_recvfrom(int sd, char *buffer, int buflen, int flags, return rcvlen; } -int -Curl_os400_getpeername(int sd, struct sockaddr *addr, int *addrlen) +int Curl_os400_getpeername(int sd, struct sockaddr *addr, int *addrlen) { struct sockaddr_storage laddr; int laddrlen = sizeof(laddr); - int retcode = getpeername(sd, (struct sockaddr *) &laddr, &laddrlen); + int retcode = getpeername(sd, (struct sockaddr *)&laddr, &laddrlen); if(!retcode) { laddrlen = sockaddr2ascii(addr, *addrlen, &laddr, laddrlen); @@ -976,12 +938,11 @@ Curl_os400_getpeername(int sd, struct sockaddr *addr, int *addrlen) return retcode; } -int -Curl_os400_getsockname(int sd, struct sockaddr *addr, int *addrlen) +int Curl_os400_getsockname(int sd, struct sockaddr *addr, int *addrlen) { struct sockaddr_storage laddr; int laddrlen = sizeof(laddr); - int retcode = getsockname(sd, (struct sockaddr *) &laddr, &laddrlen); + int retcode = getsockname(sd, (struct sockaddr *)&laddr, &laddrlen); if(!retcode) { laddrlen = sockaddr2ascii(addr, *addrlen, &laddr, laddrlen); @@ -993,17 +954,14 @@ Curl_os400_getsockname(int sd, struct sockaddr *addr, int *addrlen) return retcode; } - #ifdef HAVE_LIBZ -const char * -Curl_os400_zlibVersion(void) +const char *Curl_os400_zlibVersion(void) { return set_thread_string(LK_ZLIB_VERSION, zlibVersion()); } - -int -Curl_os400_inflateInit_(z_streamp strm, const char *version, int stream_size) +int Curl_os400_inflateInit_(z_streamp strm, const char *version, + int stream_size) { z_const char *msgb4 = strm->msg; int ret; @@ -1016,9 +974,8 @@ Curl_os400_inflateInit_(z_streamp strm, const char *version, int stream_size) return ret; } -int -Curl_os400_inflateInit2_(z_streamp strm, int windowBits, - const char *version, int stream_size) +int Curl_os400_inflateInit2_(z_streamp strm, int windowBits, + const char *version, int stream_size) { z_const char *msgb4 = strm->msg; int ret; @@ -1031,8 +988,7 @@ Curl_os400_inflateInit2_(z_streamp strm, int windowBits, return ret; } -int -Curl_os400_inflate(z_streamp strm, int flush) +int Curl_os400_inflate(z_streamp strm, int flush) { z_const char *msgb4 = strm->msg; int ret; @@ -1045,8 +1001,7 @@ Curl_os400_inflate(z_streamp strm, int flush) return ret; } -int -Curl_os400_inflateEnd(z_streamp strm) +int Curl_os400_inflateEnd(z_streamp strm) { z_const char *msgb4 = strm->msg; int ret; diff --git a/packages/OS400/os400sys.h b/packages/OS400/os400sys.h index d5ff412f2852..eb2cdb828ace 100644 --- a/packages/OS400/os400sys.h +++ b/packages/OS400/os400sys.h @@ -28,30 +28,27 @@ #ifndef __OS400_SYS_ #define __OS400_SYS_ - /* Per-thread item identifiers. */ typedef enum { - LK_GSK_ERROR, - LK_LDAP_ERROR, - LK_CURL_VERSION, - LK_VERSION_INFO, - LK_VERSION_INFO_DATA, - LK_EASY_STRERROR, - LK_SHARE_STRERROR, - LK_MULTI_STRERROR, - LK_URL_STRERROR, - LK_ZLIB_VERSION, - LK_ZLIB_MSG, - LK_LAST -} localkey_t; - - -extern char * (* Curl_thread_buffer)(localkey_t key, long size); - + LK_GSK_ERROR, + LK_LDAP_ERROR, + LK_CURL_VERSION, + LK_VERSION_INFO, + LK_VERSION_INFO_DATA, + LK_EASY_STRERROR, + LK_SHARE_STRERROR, + LK_MULTI_STRERROR, + LK_URL_STRERROR, + LK_ZLIB_VERSION, + LK_ZLIB_MSG, + LK_LAST +} localkey_t; + +extern char *(*Curl_thread_buffer)(localkey_t key, long size); /* Maximum string expansion factor due to character code conversion. */ -#define MAX_CONV_EXPANSION 4 /* Can deal with UTF-8. */ +#define MAX_CONV_EXPANSION 4 /* Can deal with UTF-8. */ #endif diff --git a/packages/OS400/rpg-examples/HEADERAPI b/packages/OS400/rpg-examples/HEADERAPI index 2046306bb80b..f6ef80bbd4fb 100644 --- a/packages/OS400/rpg-examples/HEADERAPI +++ b/packages/OS400/rpg-examples/HEADERAPI @@ -1,4 +1,4 @@ - * Curl header API: extract headers post transfer + * curl header API: extract headers post transfer * h DFTACTGRP(*NO) ACTGRP(*NEW) h OPTION(*NOSHOWCPY) diff --git a/packages/OS400/rpg-examples/HTTPPOST b/packages/OS400/rpg-examples/HTTPPOST index 9a562e9084a1..8e5d0d74bbda 100644 --- a/packages/OS400/rpg-examples/HTTPPOST +++ b/packages/OS400/rpg-examples/HTTPPOST @@ -1,4 +1,4 @@ - * Curl MIME post data and display response + * curl MIME post data and display response * h DFTACTGRP(*NO) ACTGRP(*NEW) h OPTION(*NOSHOWCPY) diff --git a/packages/OS400/rpg-examples/INMEMORY b/packages/OS400/rpg-examples/INMEMORY index ab425fc22fc9..7111d565e9a5 100644 --- a/packages/OS400/rpg-examples/INMEMORY +++ b/packages/OS400/rpg-examples/INMEMORY @@ -1,4 +1,4 @@ - * Curl get in memory and count HTML tags + * curl get in memory and count HTML tags * h DFTACTGRP(*NO) ACTGRP(*NEW) h OPTION(*NOSHOWCPY) diff --git a/packages/OS400/rpg-examples/SIMPLE1 b/packages/OS400/rpg-examples/SIMPLE1 index e1286d121514..2d2296ed40bd 100644 --- a/packages/OS400/rpg-examples/SIMPLE1 +++ b/packages/OS400/rpg-examples/SIMPLE1 @@ -1,4 +1,4 @@ - * Curl simple URL request + * curl simple URL request * h DFTACTGRP(*NO) ACTGRP(*NEW) h OPTION(*NOSHOWCPY) diff --git a/packages/OS400/rpg-examples/SIMPLE2 b/packages/OS400/rpg-examples/SIMPLE2 index b0c590cc290c..2fead8517cdb 100644 --- a/packages/OS400/rpg-examples/SIMPLE2 +++ b/packages/OS400/rpg-examples/SIMPLE2 @@ -1,4 +1,4 @@ - * Curl simple URL request (free-format RPG) + * curl simple URL request (free-format RPG) * ctl-opt dftactgrp(*NO) actgrp(*NEW) option(*NOSHOWCPY) diff --git a/packages/OS400/rpg-examples/SMTPSRCMBR b/packages/OS400/rpg-examples/SMTPSRCMBR index d11ea963072e..7e3a3fce6c75 100644 --- a/packages/OS400/rpg-examples/SMTPSRCMBR +++ b/packages/OS400/rpg-examples/SMTPSRCMBR @@ -1,4 +1,4 @@ - * Curl SMTP send source member as attachment + * curl SMTP send source member as attachment * h DFTACTGRP(*NO) ACTGRP(*NEW) h OPTION(*NOSHOWCPY) diff --git a/packages/vms/build_gnv_curl_pcsi_desc.com b/packages/vms/build_gnv_curl_pcsi_desc.com index 85674261ce38..566384de0257 100644 --- a/packages/vms/build_gnv_curl_pcsi_desc.com +++ b/packages/vms/build_gnv_curl_pcsi_desc.com @@ -22,7 +22,7 @@ $! $! The PCSI system can really only handle ODS-2 format filenames and $! assumes that there is only one source directory. It also assumes that $! all destination files with the same name come from the same source file. -$! Fortunately CURL does not trip most of these issues, so those steps +$! Fortunately curl does not trip most of these issues, so those steps $! above are marked N/A. $! $! A rename action section is needed to make sure that the files are diff --git a/packages/vms/build_gnv_curl_pcsi_text.com b/packages/vms/build_gnv_curl_pcsi_text.com index 8f109c1e7e4e..b67ad8f18797 100644 --- a/packages/vms/build_gnv_curl_pcsi_text.com +++ b/packages/vms/build_gnv_curl_pcsi_text.com @@ -2,9 +2,9 @@ $! File: Build_GNV_curl_pcsi_text.com $! $! Build the *.pcsi$text file from the four components: $! 1. Generated =product header section -$! 2. [--]readme. file from the Curl distribution, modified to fit +$! 2. [--]readme. file from the curl distribution, modified to fit $! a pcsi$text file format. -$! 3. [--]copying file from the Curl distribution, modified to fit +$! 3. [--]copying file from the curl distribution, modified to fit $! a pcsi$text file format. $! 4. Generated Producer section. $! diff --git a/packages/vms/build_gnv_curl_release_notes.com b/packages/vms/build_gnv_curl_release_notes.com index 0da94454d5be..89b30ecbe99e 100644 --- a/packages/vms/build_gnv_curl_release_notes.com +++ b/packages/vms/build_gnv_curl_release_notes.com @@ -3,7 +3,7 @@ $! $! Build the release note file from the four components: $! 1. The curl_release_note_start.txt $! 2. The hp_ssl_release_info.txt -$! 3. [--]readme. file from the Curl distribution. +$! 3. [--]readme. file from the curl distribution. $! 4. The Curl_gnv-build_steps.txt. $! $! Set the name of the release notes from the GNV_PCSI_FILENAME_BASE @@ -42,7 +42,7 @@ $ curl_readme = f$search("sys$disk:[--]$README.") $ endif $ if curl_readme .eqs. "" $ then -$ write sys$output "Can not find Curl readme file." +$ write sys$output "Can not find curl readme file." $ goto all_exit $ endif $! @@ -53,7 +53,7 @@ $ curl_copying = f$search("sys$disk:[--]$COPYING.") $ endif $ if curl_copying .eqs. "" $ then -$ write sys$output "Can not find Curl copying file." +$ write sys$output "Can not find curl copying file." $ goto all_exit $ endif $! @@ -64,7 +64,7 @@ $ vms_readme = f$search("sys$disk:[]$README.") $ endif $ if vms_readme .eqs. "" $ then -$ write sys$output "Can not find VMS specific Curl readme file." +$ write sys$output "Can not find VMS specific curl readme file." $ goto all_exit $ endif $! @@ -75,7 +75,7 @@ $ curl_release_notes = f$search("sys$disk:[--]$RELEASE-NOTES.") $ endif $ if curl_release_notes .eqs. "" $ then -$ write sys$output "Can not find Curl release-notes file." +$ write sys$output "Can not find curl release-notes file." $ goto all_exit $ endif $! diff --git a/packages/vms/build_vms.com b/packages/vms/build_vms.com index d8f89f6ef436..7ce36178056d 100644 --- a/packages/vms/build_vms.com +++ b/packages/vms/build_vms.com @@ -1,6 +1,6 @@ $! BUILD_VMS.COM $! -$! I've taken the original build_vms.com, supplied by Nico Baggus, if +$! I have taken the original build_vms.com, supplied by Nico Baggus, if $! memory serves me correctly, and made some modifications. $! $! SSL support is controlled by logical names. If SSL$INCLUDE is @@ -45,14 +45,14 @@ $! LIST Create C compiler listings and linker maps. $! /list/show=(expan,includ)/machine $! FULLLIST Full detailed listing. $! /list/show=(all, nomessages)/machine -$! NOHPSSL Don't use HP SSL, even if available. +$! NOHPSSL Do not use HP SSL, even if available. $! Note, you must match the pointer size that the OpenSSL $! shared image expects. This procedure will select the $! correct HP OpenSSL image. -$! NOSSL Don't use any SSL, even if available. +$! NOSSL Do not use any SSL, even if available. $! OSSLOLB Use OpenSSL object libraries (.OLB), even if shared $! images (.EXE) are available. -$! NOZLIB Don't use GNV$ZLIB shared image even if available. +$! NOZLIB Do not use GNV$ZLIB shared image even if available. $! REALCLEAN Delete product files for all host architectures. (No $! build done.) Alias for CLEAN_ALL $! @@ -516,7 +516,7 @@ $ endif $! $! $! CC /LIST, LINK /MAP, and MESSAGE /LIST are defaults in batch mode, -$! so be explicit when they're not desired. +$! so be explicit when they are not desired. $! $ $ if list .eq. 0 @@ -744,7 +744,7 @@ $ endif $ if ((f$search(ossl_lib1) .eqs. "") .or. - (f$search(ossl_lib2) .eqs. "")) $ then -$ write sys$output "Can't find OpenSSL ''msg':" +$ write sys$output "Cannot find OpenSSL ''msg':" $ write sys$output " ''ossl_lib1'" $ write sys$output " ''ossl_lib2'" $ goto Common_Exit @@ -943,7 +943,7 @@ $ reset = f$search( "reset", 1) $Loop: $ file = f$search( search, 1) $ if file .eqs. "" then goto EndLoop -$! Skip a name if it's in the P4 exclusion list. +$! Skip a name if it is in the P4 exclusion list. $ if (p4 .nes. "") $ then $ name__ = "," + - @@ -1016,7 +1016,7 @@ $ endif $ ENDSUBROUTINE ! Compile $! $! Do a diff of the file specified in P1 with that in P2. If different -$! copy P1 to P2. This also covers if P2 doesn't exist, but not if P2 +$! copy P1 to P2. This also covers if P2 does not exist, but not if P2 $! is an invalid filespec. $! $MoveIfDiff: subroutine diff --git a/packages/vms/compare_curl_source.com b/packages/vms/compare_curl_source.com index 13ff4667f931..b63080620ec7 100644 --- a/packages/vms/compare_curl_source.com +++ b/packages/vms/compare_curl_source.com @@ -255,7 +255,7 @@ $ then $ ref_fname = f$edit(ref_fname, "LOWERCASE") $ endif $! -$! These files are in the wrong format for VMS diff, and we don't change them. +$! These files are in the wrong format for VMS diff, and we do not change them. $ ref_skip = 0 $ if ref_type .eqs. ".PDF" then ref_skip = 1 $ if ref_type .eqs. ".HTML" then ref_skip = 1 diff --git a/packages/vms/curl_crtl_init.c b/packages/vms/curl_crtl_init.c index 90bcb4c3599c..7966a38f820b 100644 --- a/packages/vms/curl_crtl_init.c +++ b/packages/vms/curl_crtl_init.c @@ -33,7 +33,7 @@ * will turn on some CRTL features that are not enabled by default. * * The CRTL features can also be turned on via logical names, but that - * impacts all programs and some aren't ready, willing, or able to handle + * impacts all programs and some are not ready, willing, or able to handle * those settings. * * On VMS versions that are too old to use the feature setting API, this @@ -78,34 +78,29 @@ struct itmlst_3 { #pragma member_alignment restore #ifdef __VAX -#define ENABLE "ENABLE" +#define ENABLE "ENABLE" #define DISABLE "DISABLE" #else -#define ENABLE TRUE +#define ENABLE TRUE #define DISABLE 0 -int decc$feature_get_index (const char *name); -int decc$feature_set_value (int index, int mode, int value); +int decc$feature_get_index(const char *name); +int decc$feature_set_value(int index, int mode, int value); #endif -int SYS$TRNLNM( - const unsigned long *attr, - const struct dsc$descriptor_s *table_dsc, - struct dsc$descriptor_s *name_dsc, - const unsigned char *acmode, - const struct itmlst_3 *item_list); -int SYS$CRELNM( - const unsigned long *attr, - const struct dsc$descriptor_s *table_dsc, - const struct dsc$descriptor_s *name_dsc, - const unsigned char *acmode, - const struct itmlst_3 *item_list); - +int SYS$TRNLNM(const unsigned long *attr, + const struct dsc$descriptor_s *table_dsc, + struct dsc$descriptor_s *name_dsc, + const unsigned char *acmode, + const struct itmlst_3 *item_list); +int SYS$CRELNM(const unsigned long *attr, + const struct dsc$descriptor_s *table_dsc, + const struct dsc$descriptor_s *name_dsc, + const unsigned char *acmode, + const struct itmlst_3 *item_list); /* Take all the fun out of simply looking up a logical name */ -static int sys_trnlnm(const char *logname, - char *value, - int value_len) +static int sys_trnlnm(const char *logname, char *value, int value_len) { const $DESCRIPTOR(table_dsc, "LNM$FILE_DEV"); const unsigned long attr = LNM$M_CASE_BLIND; @@ -140,8 +135,7 @@ static int sys_trnlnm(const char *logname, } /* How to simply create a logical name */ -static int sys_crelnm(const char *logname, - const char *value) +static int sys_crelnm(const char *logname, const char *value) { int ret_val; const char *proc_table = "LNM$PROCESS_TABLE"; @@ -149,12 +143,12 @@ static int sys_crelnm(const char *logname, struct dsc$descriptor_s logname_dsc; struct itmlst_3 item_list[2]; - proc_table_dsc.dsc$a_pointer = (char *) proc_table; + proc_table_dsc.dsc$a_pointer = (char *)proc_table; proc_table_dsc.dsc$w_length = strlen(proc_table); proc_table_dsc.dsc$b_dtype = DSC$K_DTYPE_T; proc_table_dsc.dsc$b_class = DSC$K_CLASS_S; - logname_dsc.dsc$a_pointer = (char *) logname; + logname_dsc.dsc$a_pointer = (char *)logname; logname_dsc.dsc$w_length = strlen(logname); logname_dsc.dsc$b_dtype = DSC$K_DTYPE_T; logname_dsc.dsc$b_class = DSC$K_CLASS_S; @@ -172,8 +166,7 @@ static int sys_crelnm(const char *logname, return ret_val; } - - /* Start of DECC RTL Feature handling */ +/* Start of DECC RTL Feature handling */ /* ** Sets default value for a feature @@ -191,7 +184,7 @@ static void set_feature_default(const char *name, int value) index = decc$feature_get_index(name); if(index > 0) - decc$feature_set_value (index, 0, value); + decc$feature_set_value(index, 0, value); } #endif @@ -202,7 +195,7 @@ static void set_features(void) int use_unix_settings = 1; status = sys_trnlnm("GNV$UNIX_SHELL", - unix_shell_name, sizeof(unix_shell_name) -1); + unix_shell_name, sizeof(unix_shell_name) - 1); if(!$VMS_STATUS_SUCCESS(status)) { use_unix_settings = 0; } @@ -213,7 +206,6 @@ static void set_features(void) /* We always want the new parse style */ set_feature_default("DECC$ARGV_PARSE_STYLE", ENABLE); - /* Unless we are in POSIX compliant mode, we want the old POSIX root * enabled. */ @@ -237,14 +229,14 @@ static void set_features(void) set_feature_default("DECC$EXEC_FILEATTR_INHERITANCE", 2); #endif - /* Don't display trailing dot after files without type */ + /* Do not display trailing dot after files without type */ set_feature_default("DECC$READDIR_DROPDOTNOTYPE", ENABLE); /* For standard output channels buffer output until terminator */ /* Gets rid of output logs with single character lines in them. */ set_feature_default("DECC$STDIO_CTX_EOL", ENABLE); - /* Fix mv aa.bb aa */ + /* Fix mv aa.bb aa */ set_feature_default("DECC$RENAME_NO_INHERIT", ENABLE); if(use_unix_settings) { @@ -263,7 +255,6 @@ static void set_features(void) set_feature_default("DECC$FILE_OWNER_UNIX", ENABLE); set_feature_default("DECC$POSIX_SEEK_STREAM_FILE", ENABLE); - } else { set_feature_default("DECC$FILENAME_UNIX_REPORT", ENABLE); @@ -283,13 +274,12 @@ static void set_features(void) /* Set strtol to proper behavior */ set_feature_default("DECC$STRTOL_ERANGE", ENABLE); - /* Commented here to prevent future bugs: A program or user should */ + /* Commented here to prevent future bugs: A program or user should */ /* never ever enable DECC$POSIX_STYLE_UID. */ /* It will probably break all code that accesses UIDs */ - /* do_not_set_default ("DECC$POSIX_STYLE_UID", TRUE); */ + /* do_not_set_default("DECC$POSIX_STYLE_UID", TRUE); */ } - /* Some boilerplate to force this to be a proper LIB$INITIALIZE section */ #pragma nostandard @@ -307,7 +297,7 @@ static void set_features(void) # endif #endif /* Set our contribution to the LIB$INITIALIZE array */ -void (* const iniarray[])(void) = {set_features }; +void (* const iniarray[])(void) = { set_features }; #ifndef __VAX # if __INITIAL_POINTER_SIZE # pragma __pointer_size __restore @@ -316,7 +306,6 @@ void (* const iniarray[])(void) = {set_features }; # endif #endif - /* ** Force a reference to LIB$INITIALIZE to ensure it ** exists in the image. @@ -325,7 +314,7 @@ int LIB$INITIALIZE(void); #ifdef __DECC #pragma extern_model strict_refdef #endif - int lib_init_ref = (int) LIB$INITIALIZE; +int lib_init_ref = (int)LIB$INITIALIZE; #ifdef __DECC #pragma extern_model restore #pragma standard diff --git a/packages/vms/curl_gnv_build_steps.txt b/packages/vms/curl_gnv_build_steps.txt index b7ea95219b51..c84431f7faee 100644 --- a/packages/vms/curl_gnv_build_steps.txt +++ b/packages/vms/curl_gnv_build_steps.txt @@ -16,11 +16,11 @@ From File: curl_gnv_build_steps.txt SPDX-License-Identifier: ISC -Currently building Curl using GNV takes longer than building Curl via DCL. +Currently building curl using GNV takes longer than building curl via DCL. The GNV procedure actually uses the same configure and makefiles that Unix builds use. -Building CURL on OpenVMS using GNV requires GNV V2.1-2 or the updated +Building curl on OpenVMS using GNV requires GNV V2.1-2 or the updated images that are available via anonymous FTP at encompasserve.org in the gnv directory. It also requires the GNV Bash 4.2.45 kit as an update from the same location or from the sourceforge.net GNV project. @@ -38,7 +38,7 @@ time that this document was written. [gnv.common_src]curl_*_original_src.bck is the original source of the curl kit as provided by the curl project. [gnv.vms_src]curl-*_vms_src.bck, if present, has the OpenVMS specific files that are used for building that are not yet in -the curl source kits for that release distributed https://curl.se +the curl source kits for that release distributed https://curl.se/ These backup savesets should be restored to different directory trees on an ODS-5 volume(s) which are referenced by concealed rooted logical names. @@ -48,7 +48,7 @@ VMS_ROOT: is for the source files that are specific to OpenVMS. Note, you should create the VMS_ROOT: directory tree even if it is initially empty. This is where you should put edits if you are making changes. -LCL_ROOT: is manually created to have the same base and sub-directories as +LCL_ROOT: is manually created to have the same base and subdirectories as SRC_ROOT: and VMS_ROOT: The logical name REF_ROOT: may be defined to be a search list for @@ -100,7 +100,7 @@ Note to builders: GNV currently has a bug where configure scripts take a long time to run. Some of the configure steps take a while to complete, and on a 600 Mhz -DS10 with IDE disks, taking an hour to run the CURL configure is normal. +DS10 with IDE disks, taking an hour to run the curl configure is normal. The following messages can be ignored and may get fixed in a future version of GNV. The GNV$*.OPT files are used to find the libraries as many have diff --git a/packages/vms/curl_release_note_start.txt b/packages/vms/curl_release_note_start.txt index 62b2836359fa..1a67b36020b0 100644 --- a/packages/vms/curl_release_note_start.txt +++ b/packages/vms/curl_release_note_start.txt @@ -16,16 +16,16 @@ OpenVMS specific building and kitting instructions are after the standard curl readme file. This product may be available for your platform in a PCSI kit. The source kit -contains files for building CURL using GNV or with a DCL procedure. +contains files for building curl using GNV or with a DCL procedure. The GNV based build creates a libcurl share imaged which is supplied in the PCSI kit. -This version of CURL will return VMS compatible status codes when run from +This version of curl will return VMS compatible status codes when run from DCL and Unix compatible exit codes and messages when run with the SHELL environment variable set. -This port of Curl uses the OpenSSL, Ldap, and Kerberos V5 that are bundled +This port of curl uses the OpenSSL, Ldap, and Kerberos V5 that are bundled with OpenVMS or supplied as updates by HP. Ldap and Kerberos are not available on the VAX platform. See section below for a special note about HP OpenSSL on Alpha and IA64. @@ -61,7 +61,7 @@ For the HP SSL work around to work for GNV do the following: Similar workarounds will be needed for any program linked with GNV$LIBCURL until the HP OpenSSL is upgraded to the current 1.4 version or later. -If you are installing a "daily" build instead of a release build of Curl, some +If you are installing a "daily" build instead of a release build of curl, some things have been changed so that it can be installed at the same time as a production build without conflicts. diff --git a/packages/vms/curl_startup.com b/packages/vms/curl_startup.com index e90bbecbb9d6..7e5b2729d810 100644 --- a/packages/vms/curl_startup.com +++ b/packages/vms/curl_startup.com @@ -1,6 +1,6 @@ $! File: curl_Startup.com $! -$! Procedure to setup the CURL libraries for use by programs from the +$! Procedure to setup the curl libraries for use by programs from the $! VMS SYSTARTUP*.COM procedure. $! $! Copyright (C) John Malmberg @@ -75,7 +75,7 @@ $ define/system/exec gnv$curl_ssl_libcryptoshr32 'curl_ssl_libcrypto32' $ define/system/exec gnv$curl_ssl_libsslshr32 'curl_ssl_libssl32' $! $! -$! CURL setup +$! curl setup $ define/system/exec gnv$libcurl gnv$gnu:[usr.lib]GNV$LIBCURL.EXE $ define/system/exec gnv$curl_include gnv$gnu:[usr.include.curl] $ if .not. f$file_attributes("gnv$libcurl", "known") diff --git a/packages/vms/curlmsg.h b/packages/vms/curlmsg.h index 9b5c4c76d144..f05c3a8f5a03 100644 --- a/packages/vms/curlmsg.h +++ b/packages/vms/curlmsg.h @@ -50,93 +50,93 @@ /* IF YOU UPDATE THIS FILE, UPDATE CURLMSG_VMS.H SO THAT THEY ARE IN SYNC */ /* */ -#define CURL_FACILITY 3841 -#define CURL_OK 251756553 -#define CURL_UNSUPPORTED_PROTOCOL 251756562 -#define CURL_FAILED_INIT 251756570 -#define CURL_URL_MALFORMAT 251756578 -#define CURL_OBSOLETE4 251756586 -#define CURL_COULDNT_RESOLVE_PROXY 251756594 -#define CURL_COULDNT_RESOLVE_HOST 251756602 -#define CURL_COULDNT_CONNECT 251756610 -#define CURL_WEIRD_SERVER_REPLY 251756618 +#define CURL_FACILITY 3841 +#define CURL_OK 251756553 +#define CURL_UNSUPPORTED_PROTOCOL 251756562 +#define CURL_FAILED_INIT 251756570 +#define CURL_URL_MALFORMAT 251756578 +#define CURL_OBSOLETE4 251756586 +#define CURL_COULDNT_RESOLVE_PROXY 251756594 +#define CURL_COULDNT_RESOLVE_HOST 251756602 +#define CURL_COULDNT_CONNECT 251756610 +#define CURL_WEIRD_SERVER_REPLY 251756618 #define CURL_FTP_WEIRD_SERVER_REPLY CURL_WEIRD_SERVER_REPLY -#define CURL_FTP_ACCESS_DENIED 251756626 -#define CURL_OBSOLETE10 251756634 -#define CURL_FTP_WEIRD_PASS_REPLY 251756642 -#define CURL_OBSOLETE12 251756650 -#define CURL_FTP_WEIRD_PASV_REPLY 251756658 -#define CURL_FTP_WEIRD_227_FORMAT 251756666 -#define CURL_FTP_CANT_GET_HOST 251756674 -#define CURL_OBSOLETE16 251756682 -#define CURL_FTP_COULDNT_SET_TYPE 251756690 -#define CURL_PARTIAL_FILE 251756698 -#define CURL_FTP_COULDNT_RETR_FILE 251756706 -#define CURL_OBSOLETE20 251756714 -#define CURL_QUOTE_ERROR 251756722 -#define CURL_HTTP_RETURNED_ERROR 251756730 -#define CURL_WRITE_ERROR 251756738 -#define CURL_OBSOLETE24 251756746 -#define CURL_UPLOAD_FAILED 251756754 -#define CURL_READ_ERROR 251756762 -#define CURL_OUT_OF_MEMORY 251756770 -#define CURL_OPERATION_TIMEOUTED 251756778 -#define CURL_OBSOLETE29 251756786 -#define CURL_FTP_PORT_FAILED 251756794 -#define CURL_FTP_COULDNT_USE_REST 251756802 -#define CURL_OBSOLETE32 251756810 -#define CURL_RANGE_ERROR 251756818 -#define CURL_HTTP_POST_ERROR 251756826 -#define CURL_SSL_CONNECT_ERROR 251756834 -#define CURL_BAD_DOWNLOAD_RESUME 251756842 +#define CURL_FTP_ACCESS_DENIED 251756626 +#define CURL_OBSOLETE10 251756634 +#define CURL_FTP_WEIRD_PASS_REPLY 251756642 +#define CURL_OBSOLETE12 251756650 +#define CURL_FTP_WEIRD_PASV_REPLY 251756658 +#define CURL_FTP_WEIRD_227_FORMAT 251756666 +#define CURL_FTP_CANT_GET_HOST 251756674 +#define CURL_OBSOLETE16 251756682 +#define CURL_FTP_COULDNT_SET_TYPE 251756690 +#define CURL_PARTIAL_FILE 251756698 +#define CURL_FTP_COULDNT_RETR_FILE 251756706 +#define CURL_OBSOLETE20 251756714 +#define CURL_QUOTE_ERROR 251756722 +#define CURL_HTTP_RETURNED_ERROR 251756730 +#define CURL_WRITE_ERROR 251756738 +#define CURL_OBSOLETE24 251756746 +#define CURL_UPLOAD_FAILED 251756754 +#define CURL_READ_ERROR 251756762 +#define CURL_OUT_OF_MEMORY 251756770 +#define CURL_OPERATION_TIMEOUTED 251756778 +#define CURL_OBSOLETE29 251756786 +#define CURL_FTP_PORT_FAILED 251756794 +#define CURL_FTP_COULDNT_USE_REST 251756802 +#define CURL_OBSOLETE32 251756810 +#define CURL_RANGE_ERROR 251756818 +#define CURL_HTTP_POST_ERROR 251756826 +#define CURL_SSL_CONNECT_ERROR 251756834 +#define CURL_BAD_DOWNLOAD_RESUME 251756842 #define CURL_FILE_COULDNT_READ_FILE 251756850 -#define CURL_LDAP_CANNOT_BIND 251756858 -#define CURL_LDAP_SEARCH_FAILED 251756866 -#define CURL_OBSOLETE40 251756874 -#define CURL_FUNCTION_NOT_FOUND 251756882 -#define CURL_ABORTED_BY_CALLBACK 251756890 -#define CURL_BAD_FUNCTION_ARGUMENT 251756898 -#define CURL_OBSOLETE44 251756906 -#define CURL_INTERFACE_FAILED 251756914 -#define CURL_OBSOLETE46 251756922 -#define CURL_TOO_MANY_REDIRECTS 251756930 -#define CURL_UNKNOWN_TELNET_OPTION 251756938 -#define CURL_TELNET_OPTION_SYNTAX 251756946 -#define CURL_OBSOLETE50 251756954 -#define CURL_PEER_FAILED_VERIF 251756962 -#define CURL_GOT_NOTHING 251756970 -#define CURL_SSL_ENGINE_NOTFOUND 251756978 -#define CURL_SSL_ENGINE_SETFAILED 251756986 -#define CURL_SEND_ERROR 251756994 -#define CURL_RECV_ERROR 251757002 -#define CURL_OBSOLETE57 251757010 -#define CURL_SSL_CERTPROBLEM 251757018 -#define CURL_SSL_CIPHER 251757026 -#define CURL_SSL_CACERT 251757034 -#define CURL_BAD_CONTENT_ENCODING 251757042 -#define CURL_LDAP_INVALID_URL 251757050 -#define CURL_FILESIZE_EXCEEDED 251757058 -#define CURL_USE_SSL_FAILED 251757066 -#define CURL_SEND_FAIL_REWIND 251757074 -#define CURL_SSL_ENGINE_INITFAILED 251757082 -#define CURL_LOGIN_DENIED 251757090 -#define CURL_TFTP_NOTFOUND 251757098 -#define CURL_TFTP_PERM 251757106 -#define CURL_REMOTE_DISK_FULL 251757114 -#define CURL_TFTP_ILLEGAL 251757122 -#define CURL_TFTP_UNKNOWNID 251757130 -#define CURL_REMOTE_FILE_EXISTS 251757138 -#define CURL_TFTP_NOSUCHUSER 251757146 -#define CURL_CONV_FAILED 251757154 -#define CURL_CONV_REQD 251757162 -#define CURL_SSL_CACERT_BADFILE 251757170 -#define CURL_REMOTE_FILE_NOT_FOUND 251757178 -#define CURL_SSH 251757186 -#define CURL_SSL_SHUTDOWN_FAILED 251757194 -#define CURL_AGAIN 251757202 -#define CURL_SSL_CRL_BADFILE 251757210 -#define CURL_SSL_ISSUER_ERROR 251757218 -#define CURL_CURL_LAST 251757226 +#define CURL_LDAP_CANNOT_BIND 251756858 +#define CURL_LDAP_SEARCH_FAILED 251756866 +#define CURL_OBSOLETE40 251756874 +#define CURL_FUNCTION_NOT_FOUND 251756882 +#define CURL_ABORTED_BY_CALLBACK 251756890 +#define CURL_BAD_FUNCTION_ARGUMENT 251756898 +#define CURL_OBSOLETE44 251756906 +#define CURL_INTERFACE_FAILED 251756914 +#define CURL_OBSOLETE46 251756922 +#define CURL_TOO_MANY_REDIRECTS 251756930 +#define CURL_UNKNOWN_TELNET_OPTION 251756938 +#define CURL_TELNET_OPTION_SYNTAX 251756946 +#define CURL_OBSOLETE50 251756954 +#define CURL_PEER_FAILED_VERIF 251756962 +#define CURL_GOT_NOTHING 251756970 +#define CURL_SSL_ENGINE_NOTFOUND 251756978 +#define CURL_SSL_ENGINE_SETFAILED 251756986 +#define CURL_SEND_ERROR 251756994 +#define CURL_RECV_ERROR 251757002 +#define CURL_OBSOLETE57 251757010 +#define CURL_SSL_CERTPROBLEM 251757018 +#define CURL_SSL_CIPHER 251757026 +#define CURL_SSL_CACERT 251757034 +#define CURL_BAD_CONTENT_ENCODING 251757042 +#define CURL_LDAP_INVALID_URL 251757050 +#define CURL_FILESIZE_EXCEEDED 251757058 +#define CURL_USE_SSL_FAILED 251757066 +#define CURL_SEND_FAIL_REWIND 251757074 +#define CURL_SSL_ENGINE_INITFAILED 251757082 +#define CURL_LOGIN_DENIED 251757090 +#define CURL_TFTP_NOTFOUND 251757098 +#define CURL_TFTP_PERM 251757106 +#define CURL_REMOTE_DISK_FULL 251757114 +#define CURL_TFTP_ILLEGAL 251757122 +#define CURL_TFTP_UNKNOWNID 251757130 +#define CURL_REMOTE_FILE_EXISTS 251757138 +#define CURL_TFTP_NOSUCHUSER 251757146 +#define CURL_CONV_FAILED 251757154 +#define CURL_CONV_REQD 251757162 +#define CURL_SSL_CACERT_BADFILE 251757170 +#define CURL_REMOTE_FILE_NOT_FOUND 251757178 +#define CURL_SSH 251757186 +#define CURL_SSL_SHUTDOWN_FAILED 251757194 +#define CURL_AGAIN 251757202 +#define CURL_SSL_CRL_BADFILE 251757210 +#define CURL_SSL_ISSUER_ERROR 251757218 +#define CURL_CURL_LAST 251757226 #pragma __member_alignment __restore diff --git a/packages/vms/generate_config_vms_h_curl.com b/packages/vms/generate_config_vms_h_curl.com index d7bc8bfc8f3b..245d072d20d0 100644 --- a/packages/vms/generate_config_vms_h_curl.com +++ b/packages/vms/generate_config_vms_h_curl.com @@ -1,6 +1,6 @@ $! File: GENERATE_CONFIG_H_CURL.COM $! -$! Curl like most open source products uses a variant of a config.h file. +$! curl like most open source products uses a variant of a config.h file. $! Depending on the curl version, this could be config.h or curl_config.h. $! $! For GNV based builds, the configure script is run and that produces @@ -197,7 +197,7 @@ $write cvh "#define __CONFIG_VMS_H__" $write cvh "" $write cvh "/* Define cpu-machine-OS */" $! -$! Curl uses an OS macro to set the build environment. +$! curl uses an OS macro to set the build environment. $!---------------------------------------------------- $! Now the DCL builds usually say xxx-HP-VMS and configure scripts $! may put DEC or COMPAQ or HP for the middle part. @@ -345,7 +345,7 @@ $! $! $! I can not figure out where the C compiler is finding the ALLOCA.H file $! in the text libraries, so CONFIG_H.COM can not find it either. -$! Usually the header file name is the module name in the text library. +$! Usually the header filename is the module name in the text library. $! It does not appear to hurt anything to not find header file, so we $! are not overriding it here. $! diff --git a/packages/vms/gnv_curl_configure.sh b/packages/vms/gnv_curl_configure.sh index 21558001ed86..7e74da346323 100755 --- a/packages/vms/gnv_curl_configure.sh +++ b/packages/vms/gnv_curl_configure.sh @@ -1,6 +1,6 @@ # File: gnv_curl_configure.sh # -# Set up and run the configure script for Curl so that it can find the +# Set up and run the configure script for curl so that it can find the # proper options for VMS. # # Copyright (C) John Malmberg diff --git a/packages/vms/gnv_link_curl.com b/packages/vms/gnv_link_curl.com index 83a8e021e823..9fc944c778c9 100644 --- a/packages/vms/gnv_link_curl.com +++ b/packages/vms/gnv_link_curl.com @@ -259,7 +259,7 @@ This package is built on with the OpenSSL version listed below and requires the shared images from the HP OpenSSL product that is kitted with that version or a compatible later version. -For Alpha and IA64 platforms, see the url below to register to get the +For Alpha and IA64 platforms, see the URL below to register to get the download URL. The kit will be HP 1.4-467 or later. https://h41379.www4.hpe.com/openvms/products/ssl/ssl.html @@ -269,10 +269,10 @@ download URLs provided and put in CPQ-VAXVMS-SSL-V0101-B-1.PCSI-DCX_VAXEXE If your system can not be upgraded to a compatible version of OpenSSL, then you can extract the two shared images from the kit and place them in the [vms$common.gnv.lib]directory of the volume that you are installing GNV and -or GNV compatible components like Curl. +or GNV compatible components like curl. If GNV is installed, you must run the GNV startup procedure before these steps -and before installing Curl. +and before installing curl. 1. make sure that [vms$common.gnv.lib] exists by using the following @@ -387,7 +387,7 @@ $! $ if f$search("[.src]curl-tool_main.o") .nes. "" $ then $! From src/makefile.inc: -$! # libcurl has sources that provide functions named curlx_* that aren't +$! # libcurl has sources that provide functions named curlx_* that are not $! # part of the official API, but we reuse the code here to avoid $! # duplication. $! diff --git a/packages/vms/make_gnv_curl_install.sh b/packages/vms/make_gnv_curl_install.sh index b85ef0ced245..4723070387d0 100755 --- a/packages/vms/make_gnv_curl_install.sh +++ b/packages/vms/make_gnv_curl_install.sh @@ -1,6 +1,6 @@ # File: make_gnv_curl_install.sh # -# Set up and run the make script for Curl. +# Set up and run the make script for curl. # # This makes the library, the curl binary and attempts an install. # A search list should be set up for GNU (GNV$GNU). diff --git a/packages/vms/pcsi_gnv_curl_file_list.txt b/packages/vms/pcsi_gnv_curl_file_list.txt index 586f7e767536..9ae49d5977e0 100644 --- a/packages/vms/pcsi_gnv_curl_file_list.txt +++ b/packages/vms/pcsi_gnv_curl_file_list.txt @@ -1,7 +1,7 @@ ! File: PCSI_GNV_CURL_FILE_LIST.TXT ! ! File list for building a PCSI kit. -! Very simple format so that the parsing logic can be simple. +! Simple format so that the parsing logic can be simple. ! links first, directory second, and files third. ! ! link -> file tells procedure to create/remove a link on install/uninstall diff --git a/packages/vms/pcsi_product_gnv_curl.com b/packages/vms/pcsi_product_gnv_curl.com index 83d8fa3b6611..2369613f47f8 100644 --- a/packages/vms/pcsi_product_gnv_curl.com +++ b/packages/vms/pcsi_product_gnv_curl.com @@ -1,6 +1,6 @@ $! File: PCSI_PRODUCT_GNV_CURL.COM $! -$! This command file packages up the product CURL into a sequential +$! This command file packages up the product curl into a sequential $! format kit $! $! Copyright (C) John Malmberg @@ -85,8 +85,8 @@ $ endif $ @gnv_link_curl.com $ endif $! -$! Make sure that the release note file name is up to date -$!--------------------------------------------------------- +$! Make sure that the release note filename is up to date +$!-------------------------------------------------------- $ @BUILD_GNV_CURL_RELEASE_NOTES.COM $! $! diff --git a/packages/vms/readme b/packages/vms/readme index 042a22b8070e..7cf3fc68671d 100644 --- a/packages/vms/readme +++ b/packages/vms/readme @@ -202,17 +202,17 @@ Other Notes: This release fixes known bugs #22, and #57 in the [curl.docs]known_bugs. file. -The libcurl formdata.c module and Curl tools post form now have some +The libcurl formdata.c module and curl tools post form now have some understanding of VMS file types. Files will be posted in STREAM_LF format. -The Curl tool now has some understanding of VMS file types and will upload the +The curl tool now has some understanding of VMS file types and will upload the files in STREAM_LF format. -When CURL is uploading a VARIABLE format VMS file, it is less efficient as in +When curl is uploading a VARIABLE format VMS file, it is less efficient as in order to get the file size, it will first read the entire file once, and then read the file again for the actual upload. -The Curl tool will now always download files into STREAM_LF format. Even if a +The curl tool will now always download files into STREAM_LF format. Even if a file by that name with a different format already exists. This is needed to allow interrupted downloads to be continued. @@ -225,4 +225,4 @@ The test suites are not supported as of 7.11.0. The curlmsg.sdl and curlmsg.h files are generated from curlmsg.msg. This is not done automatically, since the .MSG file is a hand edit of the relevant stuff from the curl.h file. If you want to do this -yourself you'll need the SDL package from the freeware collection. +yourself you need the SDL package from the freeware collection. diff --git a/packages/vms/report_openssl_version.c b/packages/vms/report_openssl_version.c index dd1713b24446..d2b0d367bc49 100644 --- a/packages/vms/report_openssl_version.c +++ b/packages/vms/report_openssl_version.c @@ -35,15 +35,14 @@ #include #include -unsigned long LIB$SET_SYMBOL( - const struct dsc$descriptor_s * symbol, - const struct dsc$descriptor_s * value, - const unsigned long *table_type); +unsigned long LIB$SET_SYMBOL(const struct dsc$descriptor_s *symbol, + const struct dsc$descriptor_s *value, + const unsigned long *table_type); int main(int argc, char **argv) { void *libptr; - const char * (*ssl_version)(int t); + const char *(*ssl_version)(int t); const char *version; if(argc < 1) { @@ -53,11 +52,11 @@ int main(int argc, char **argv) libptr = dlopen(argv[1], 0); - ssl_version = (const char * (*)(int))dlsym(libptr, "SSLeay_version"); + ssl_version = (const char *(*)(int))dlsym(libptr, "SSLeay_version"); if(!ssl_version) { - ssl_version = (const char * (*)(int))dlsym(libptr, "ssleay_version"); + ssl_version = (const char *(*)(int))dlsym(libptr, "ssleay_version"); if(!ssl_version) { - ssl_version = (const char * (*)(int))dlsym(libptr, "SSLEAY_VERSION"); + ssl_version = (const char *(*)(int))dlsym(libptr, "SSLEAY_VERSION"); } } diff --git a/packages/vms/setup_gnv_curl_build.com b/packages/vms/setup_gnv_curl_build.com index 49882463f3c4..e2d058a8b955 100644 --- a/packages/vms/setup_gnv_curl_build.com +++ b/packages/vms/setup_gnv_curl_build.com @@ -1,6 +1,6 @@ $! File: setup_gnv_curl_build.com $! -$! Set up build environment for building Curl under GNV on VMS. +$! Set up build environment for building curl under GNV on VMS. $! $! GNV needs some files moved into the other directories to help with $! the configure script and the build. diff --git a/projects/README.md b/projects/README.md index 1777074c6d05..bf373accdecd 100644 --- a/projects/README.md +++ b/projects/README.md @@ -105,7 +105,7 @@ that: 3. Navigate to 'Configuration Properties > Debugging > Environment' 4. Add `PATH='Path to DLL';C:\Windows\System32;C:\Windows;C:\Windows\System32\Wbem` -... where 'Path to DLL` is the configuration specific path. For example the +... where `Path to DLL` is the configuration specific path. For example the following configurations in Visual Studio 2010 might be: DLL Debug - DLL OpenSSL (Win32): @@ -119,7 +119,7 @@ DLL Debug - DLL OpenSSL (x64): C:\Windows;C:\Windows\System32\Wbem If you are using a configuration that uses multiple third-party library DLLs -(such as DLL Debug - DLL OpenSSL - DLL libssh2) then 'Path to DLL' need to +(such as `DLL Debug - DLL OpenSSL - DLL libssh2`) then 'Path to DLL' need to contain the path to both of these. ## Notes diff --git a/projects/Windows/tmpl/curl.vcxproj b/projects/Windows/tmpl/curl.vcxproj index 940b106b74c0..d00e0b76ab37 100644 --- a/projects/Windows/tmpl/curl.vcxproj +++ b/projects/Windows/tmpl/curl.vcxproj @@ -2296,10 +2296,12 @@ CURL_LIB_CURLX_C_FILES +CURL_SRC_TOOLX_C_FILES CURL_SRC_C_FILES CURL_LIB_CURLX_H_FILES +CURL_SRC_TOOLX_H_FILES CURL_SRC_X_H_FILES CURL_SRC_H_FILES diff --git a/projects/generate.bat b/projects/generate.bat index 3aebff183e9c..e66a34aba8b1 100644 --- a/projects/generate.bat +++ b/projects/generate.bat @@ -226,6 +226,10 @@ rem for /f "delims=" %%c in ('dir /b ..\lib\vtls\*.c') do call :element lib\vtls "%%c" %3 ) else if "!var!" == "CURL_LIB_VTLS_H_FILES" ( for /f "delims=" %%h in ('dir /b ..\lib\vtls\*.h') do call :element lib\vtls "%%h" %3 + ) else if "!var!" == "CURL_SRC_TOOLX_C_FILES" ( + for /f "delims=" %%c in ('dir /b ..\src\toolx\*.c') do call :element src\toolx "%%c" %3 + ) else if "!var!" == "CURL_SRC_TOOLX_H_FILES" ( + for /f "delims=" %%h in ('dir /b ..\src\toolx\*.h') do call :element src\toolx "%%h" %3 ) else ( echo.!var!>> %3 ) diff --git a/renovate.json b/renovate.json index 102bf42521fd..7b1b02a37802 100644 --- a/renovate.json +++ b/renovate.json @@ -13,7 +13,8 @@ "commitMessagePrefix": "GHA: ", "labels": [ "CI" - ] + ], + "enabled": false }, { "matchUpdateTypes": [ @@ -21,7 +22,7 @@ "pinDigest", "digest" ], - "commitMessagePrefix": "CI: ", + "commitMessagePrefix": "GHA: ", "labels": [ "CI" ] @@ -30,7 +31,7 @@ "matchManagers": [ "custom.regex" ], - "commitMessagePrefix": "CI: ", + "commitMessagePrefix": "GHA: ", "labels": [ "CI" ] @@ -45,11 +46,12 @@ "enabled": false }, { - "description": "Schedule CodeQL updates on the 10th of each month", + "description": "Schedule package updates on the 10th of each month", "matchPackageNames": [ - "/codeql/i" + "/codeql/i", + "/ruff/i" ], - "groupName": "CodeQL", + "groupName": "monthly updates by name", "schedule": [ "* * 10 * *" ] @@ -59,7 +61,7 @@ "matchSourceUrls": [ "**/awslabs/**" ], - "groupName": "monthly updates", + "groupName": "monthly updates by URL", "schedule": [ "* * 10 * *" ] diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index dd590c910fc7..54bb814267d8 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -27,7 +27,7 @@ option(CURL_COMPLETION_ZSH "Install zsh completions" OFF) if(CURL_COMPLETION_FISH OR CURL_COMPLETION_ZSH) - if(PERL_FOUND) + if(Perl_FOUND) if(CURL_COMPLETION_FISH) set(_completion_fish "${CMAKE_CURRENT_BINARY_DIR}/curl.fish") add_custom_command(OUTPUT "${_completion_fish}" diff --git a/scripts/cd2cd b/scripts/cd2cd index 9356ade6e63b..d593e9a579ba 100755 --- a/scripts/cd2cd +++ b/scripts/cd2cd @@ -54,7 +54,6 @@ while(1) { } } - use POSIX qw(strftime); my @ts; if(defined($ENV{SOURCE_DATE_EPOCH})) { diff --git a/scripts/cd2nroff b/scripts/cd2nroff index 950011173b89..e97d1299ddbd 100755 --- a/scripts/cd2nroff +++ b/scripts/cd2nroff @@ -25,7 +25,7 @@ =begin comment -Converts a curldown file to nroff (manpage). +Converts a curldown file to nroff (man page). =end comment =cut @@ -55,10 +55,10 @@ while(@ARGV) { print < Write the output to the file name from the meta-data in the +-d Write the output to the filename from the meta-data in the specified directory, instead of writing to stdout -e If -d is used, this option can provide an added "extension", arbitrary - text really, to append to the file name. + text really, to append to the filename. -h This help text, -v Show version then exit HELP @@ -189,7 +189,7 @@ my %knowntls = ( 'GnuTLS' => 1, 'mbedTLS' => 1, 'OpenSSL' => 1, - 'rustls' => 1, + 'Rustls' => 1, 'Schannel' => 1, 'wolfSSL' => 1, 'All' => 1, @@ -373,7 +373,7 @@ sub single { my $blankline = 0; my $header = 0; - # cut off the leading path from the file name, if any + # cut off the leading path from the filename, if any $f =~ s/^(.*[\\\/])//; push @desc, ".\\\" generated by cd2nroff $cd2nroff from $f\n"; @@ -431,7 +431,7 @@ sub single { # convert backslash-'<' or '> to just the second character $d =~ s/\\([<>])/$1/g; - # mentions of curl symbols with manpages use italics by default + # mentions of curl symbols with man pages use italics by default $d =~ s/((lib|)curl([^ ]*\(3\)))/\\fI$1\\fP/gi; # backticked becomes italics @@ -515,7 +515,7 @@ sub single { $blankline++; } else { - # don't output newlines if this is the first content after a + # do not output newlines if this is the first content after a # header push @desc, "\n" if($blankline && !$header); $blankline = 0; diff --git a/scripts/cdall b/scripts/cdall index aab41b65059c..3c5c68b525b1 100755 --- a/scripts/cdall +++ b/scripts/cdall @@ -23,7 +23,7 @@ # ########################################################################### -# provide all dir names to scan on the cmdline +# provide all directory names to scan on the command-line use strict; use warnings; diff --git a/scripts/checksrc-all.pl b/scripts/checksrc-all.pl index 08ff6cfbf5fb..764895148e50 100755 --- a/scripts/checksrc-all.pl +++ b/scripts/checksrc-all.pl @@ -22,6 +22,7 @@ } @files = grep !/\/CMakeFiles\//, @files; +@files = grep !/tests\/data\/data.+\.c/, @files; @files = map { dirname($_) } @files; my @dirs = sort { $a cmp $b } keys %{{ map { $_ => 1 } @files }}; diff --git a/scripts/checksrc.pl b/scripts/checksrc.pl index 7059d6857500..8839f38bf610 100755 --- a/scripts/checksrc.pl +++ b/scripts/checksrc.pl @@ -48,64 +48,88 @@ my @ignore_line; my %banfunc = ( - "gmtime" => 1, - "localtime" => 1, - "gets" => 1, - "strtok" => 1, - "sprintf" => 1, - "snprintf" => 1, - "vsprintf" => 1, - "vsnprintf" => 1, - "aprintf" => 1, - "fprintf" => 1, - "msnprintf" => 1, - "mvsnprintf" => 1, - "printf" => 1, - "vaprintf" => 1, - "vfprintf" => 1, - "vprintf" => 1, - "sscanf" => 1, - "strcat" => 1, - "strerror" => 1, - "strncat" => 1, - "strncpy" => 1, - "strtok_r" => 1, - "strtol" => 1, - "strtoul" => 1, + "_access" => 1, "_mbscat" => 1, "_mbsncat" => 1, + "_open" => 1, "_tcscat" => 1, "_tcsdup" => 1, "_tcsncat" => 1, + "_tcsncpy" => 1, + "_waccess" => 1, "_wcscat" => 1, - "_wcsncat" => 1, "_wcsdup" => 1, - "wcsdup" => 1, + "_wcsncat" => 1, + "_wfopen" => 1, + "_wfreopen" => 1, + "_wopen" => 1, + "accept" => 1, + "accept4" => 1, + "access" => 1, + "aprintf" => 1, + "atoi" => 1, + "atol" => 1, + "calloc" => 1, + "CreateFile" => 1, + "CreateFileA" => 1, + "CreateFileW" => 1, + "fclose" => 1, + "fdopen" => 1, + "fopen" => 1, + "fprintf" => 1, + "free" => 1, + "freeaddrinfo" => 1, + "freopen" => 1, + "getaddrinfo" => 1, + "gets" => 1, + "gmtime" => 1, "LoadLibrary" => 1, "LoadLibraryA" => 1, - "LoadLibraryW" => 1, "LoadLibraryEx" => 1, "LoadLibraryExA" => 1, "LoadLibraryExW" => 1, - "WSASocket" => 1, - "WSASocketA" => 1, - "WSASocketW" => 1, - "_waccess" => 1, - "_access" => 1, - "access" => 1, - "accept" => 1, - "accept4" => 1, - "freeaddrinfo" => 1, - "getaddrinfo" => 1, + "LoadLibraryW" => 1, + "localtime" => 1, + "malloc" => 1, + "mbstowcs" => 1, + "MoveFileEx" => 1, + "MoveFileExA" => 1, + "MoveFileExW" => 1, + "msnprintf" => 1, + "mvsnprintf" => 1, + "open" => 1, + "printf" => 1, + "realloc" => 1, "recv" => 1, + "rename" => 1, "send" => 1, + "snprintf" => 1, "socket" => 1, "socketpair" => 1, - "fclose" => 1, - "fdopen" => 1, - "fopen" => 1, - "open" => 1, + "sprintf" => 1, + "sscanf" => 1, "stat" => 1, + "strcat" => 1, + "strdup" => 1, + "strerror" => 1, + "strncat" => 1, + "strncpy" => 1, + "strtok_r" => 1, + "strtok" => 1, + "strtol" => 1, + "strtoul" => 1, + "vaprintf" => 1, + "vfprintf" => 1, + "vprintf" => 1, + "vsnprintf" => 1, + "vsprintf" => 1, + "wcscpy" => 1, + "wcsdup" => 1, + "wcsncpy" => 1, + "wcstombs" => 1, + "WSASocket" => 1, + "WSASocketA" => 1, + "WSASocketW" => 1, ); my %warnings_extended = ( @@ -124,6 +148,7 @@ 'BRACEPOS' => 'wrong position for an open brace', 'BRACEWHILE' => 'A single space between open brace and while', 'COMMANOSPACE' => 'comma without following space', + "CLOSEBRACE" => 'close brace indent level vs line above is off', 'COMMENTNOSPACEEND' => 'no space before */', 'COMMENTNOSPACESTART' => 'no space following /*', 'COPYRIGHT' => 'file missing a copyright statement', @@ -131,11 +156,13 @@ 'DOBRACE' => 'A single space between do and open brace', 'EMPTYLINEBRACE' => 'Empty line before the open brace', 'EQUALSNOSPACE' => 'equals sign without following space', + 'EQUALSPACE' => 'equals sign with too many spaces following', 'EQUALSNULL' => 'if/while comparison with == NULL', 'ERRNOVAR' => 'use of bare errno define', 'EXCLAMATIONSPACE' => 'Whitespace after exclamation mark in expression', 'FIXME' => 'FIXME or TODO comment', 'FOPENMODE' => 'fopen needs a macro for the mode string', + 'IFDEFSINGLE', => 'use ifdef/ifndef for single macro checks', 'INCLUDEDUP', => 'same file is included again', 'INDENTATION' => 'wrong start column for code', 'LONGLINE' => "Line longer than $max_column", @@ -177,7 +204,7 @@ sub readskiplist { # Reads the .checksrc in $dir for any extended warnings to enable locally. # Currently there is no support for disabling warnings from the standard set, -# and since that's already handled via !checksrc! commands there is probably +# and since that is already handled via !checksrc! commands there is probably # little use to add it. sub readlocalfile { my ($file) = @_; @@ -242,7 +269,7 @@ sub checkwarn { my $nowarn=0; #if(!$warnings{$name}) { - # print STDERR "Dev! there's no description for $name!\n"; + # print STDERR "Dev! there is no description for $name!\n"; #} # checksrc.skip @@ -347,7 +374,7 @@ sub checkwarn { print " -A[rule] Accept this violation, can be used multiple times\n"; print " -a[func] Allow use of this function\n"; print " -b[func] Ban use of this function\n"; - print " -D[DIR] Directory to prepend file names\n"; + print " -D[DIR] Directory to prepend filenames\n"; print " -h Show help output\n"; print " -W[file] Skip the given file - ignore all its flaws\n"; print " -i Indent spaces. Default: 2\n"; @@ -632,6 +659,11 @@ sub scanfile { $line, length($1), $file, $l, "\/\/ comment"); } + if($l =~ /^\s*#\s*if\s+!?\s*defined\([a-zA-Z0-9_]+\)$/) { + checkwarn("IFDEFSINGLE", + $line, length($1), $file, $l, "use ifdef/ifndef for single macro checks"); + } + if($l =~ /^(\#\s*include\s+)([\">].*[>}"])/) { my ($pre, $path) = ($1, $2); if($includes{$path}) { @@ -877,6 +909,21 @@ sub scanfile { } } + # when the line starts with a brace + if($l =~ /^( *)\}/) { + my $tlen = length($1); + if($prevl =~ /^( *)(.)/) { + my $plen = length($1); + my $firstc = $2; + # skips the check if the previous line starts with a close + # brace since we see the occasional legit use of that oddity + if(($tlen + $indent) > $plen && ($firstc ne "}")) { + checkwarn("CLOSEBRACE", + $line, $plen, $file, $prevl, + "Suspicious close brace indentation"); + } + } + } # check for "} else" if($l =~ /^(.*)\} *else/) { checkwarn("BRACEELSE", @@ -942,7 +989,7 @@ sub scanfile { } # scan for use of non-binary fopen without the macro - if($l =~ /^(.*\W)(curlx_fopen|CURLX_FOPEN_LOW)\s*\([^,]*, *\"([^"]*)/) { + if($l =~ /^(.*\W)(curlx_fopen|CURLX_FOPEN_LOW|curlx_freopen|CURLX_FREOPEN_LOW)\s*\([^,]*, *\"([^"]*)/) { my $mode = $3; if($mode !~ /b/) { checkwarn("FOPENMODE", @@ -952,7 +999,7 @@ sub scanfile { } # check for open brace first on line but not first column only alert - # if previous line ended with a close paren and it wasn't a cpp line + # if previous line ended with a close paren and it was not a cpp line if(($prevl =~ /\)\z/) && ($l =~ /^( +)\{/) && !$prevp) { checkwarn("BRACEPOS", $line, length($1), $file, $ol, "badly placed open brace"); @@ -976,7 +1023,7 @@ sub scanfile { } # if the previous line starts with if/while/for AND ends with a closed - # parenthesis and there's an equal number of open and closed + # parenthesis and there is an equal number of open and closed # parentheses, check that this line is indented $indent more steps, if # not a cpp line elsif(!$prevp && ($prevl =~ /^( *)(if|while|for)(\(.*\))\z/)) { @@ -1039,6 +1086,12 @@ sub scanfile { $line, length($1)+1, $file, $ol, "no space before equals sign"); } + # check for equals sign with more than one space after it + elsif($l =~ /(.*)[a-z0-9] \= /i) { + checkwarn("EQUALSPACE", + $line, length($1)+3, $file, $ol, + "more than one space after equals sign"); + } # check for plus signs without spaces next to it if($nostr =~ /(.*)[^+]\+[a-z0-9]/i) { @@ -1165,7 +1218,6 @@ sub scanfile { } - if($errors || $warnings || $verbose) { printf "checksrc: %d errors and %d warnings\n", $errors, $warnings; if($suppressed) { diff --git a/scripts/ciconfig.pl b/scripts/ciconfig.pl index 1d8f23556434..95ce0fb877ed 100755 --- a/scripts/ciconfig.pl +++ b/scripts/ciconfig.pl @@ -108,7 +108,6 @@ ); - sub configureopts { my ($opts)=@_; my %thisin; @@ -182,15 +181,14 @@ sub scanjobs { } } -print "Never ENABLED configure options that aren't on by default\n"; +print "Never ENABLED configure options that are not on by default\n"; for my $w (sort keys %avail) { if(!$with{$w} && !$defaulton{$w}) { printf " %s\n", $w; } } - -print "ENABLED configure options that aren't available\n"; +print "ENABLED configure options that are not available\n"; for my $w (sort keys %with) { if(!$avail{$w}) { printf " %s\n", $w; diff --git a/scripts/cmakelint.sh b/scripts/cmakelint.sh index 9462081f218b..dc66829fc8c5 100755 --- a/scripts/cmakelint.sh +++ b/scripts/cmakelint.sh @@ -34,7 +34,7 @@ # cmake-lint can be installed from PyPi with the command "python3 -m pip # install cmakelang". # -# The xargs invocation is portable, but does not preserve spaces in file names. +# The xargs invocation is portable, but does not preserve spaces in filenames. # If such a file is ever added, then this can be portably fixed by switching to # "xargs -I{}" and appending {} to the end of the xargs arguments (which will # call cmakelint once per file) or by using the GNU extension "xargs -d'\n'". @@ -45,15 +45,13 @@ cd "$(dirname "$0")"/.. { if [ -n "${1:-}" ]; then - for A in "$@"; do printf "%s\n" "$A"; done + for A in "$@"; do printf '%s\n' "$A"; done elif git rev-parse --is-inside-work-tree >/dev/null 2>&1; then - git ls-files + git ls-files '**CMakeLists.txt' '*.cmake' else - # strip off the leading ./ to make the grep regexes work properly - find . -type f | sed 's@^\./@@' + find . -type f \( -name 'CMakeLists.txt' -o -name '*.cmake' \) fi -} | grep -E '(^CMake|/CMake|\.cmake$)' | grep -v -E '(\.h\.cmake|\.in|\.c)$' \ - | xargs \ +} | sort | xargs \ cmake-lint \ --suppress-decorations \ --disable \ diff --git a/scripts/completion.pl b/scripts/completion.pl index 7b689c74fbba..27e2f062e7a4 100755 --- a/scripts/completion.pl +++ b/scripts/completion.pl @@ -84,8 +84,8 @@ sub parse_main_opts { @files = readdir($dir_handle); closedir($dir_handle) || die "Unable to close handle on dir: $opts_dir due to error: $!"; - # We want regular files that end with .md and don't start with an underscore - # Edge case: MANPAGE.md doesn't start with an underscore but also isn't documentation for an option + # We want regular files that end with .md and do not start with an underscore + # Edge case: MANPAGE.md does not start with an underscore but also is not documentation for an option @files = grep { $_ =~ /\.md$/i && !/^_/ && -f "$opts_dir/$_" && $_ ne "MANPAGE.md" } @files; for my $file (@files) { @@ -145,8 +145,8 @@ sub parse_main_opts { push(@list, $option); } - # Sort longest first, because zsh won't complete an option listed - # after one that's a prefix of it. When length is equal, fall back + # Sort longest first, because zsh does not complete an option listed + # after one that is a prefix of it. When length is equal, fall back # to stringwise cmp. @list = sort { $a =~ /([^=]*)/; my $ma = $1; diff --git a/scripts/contributors.sh b/scripts/contributors.sh index ddc9bdfba032..cea72ff5e5d3 100755 --- a/scripts/contributors.sh +++ b/scripts/contributors.sh @@ -62,7 +62,7 @@ CURLWWW="${CURLWWW:-../curl-www}" git -C "$CURLWWW" log --pretty=full --use-mailmap "$start..HEAD" fi } | \ - grep -Eai '(^Author|^Commit|by):' | \ + grep -Eai '(^Author|^Commit|^ +[a-z-]+-by):' | \ cut -d: -f2- | \ cut '-d(' -f1 | \ cut '-d<' -f1 | \ diff --git a/scripts/contrithanks.sh b/scripts/contrithanks.sh index 59db5b876afd..47438701cdd4 100755 --- a/scripts/contrithanks.sh +++ b/scripts/contrithanks.sh @@ -62,7 +62,7 @@ tail -n +7 ./docs/THANKS | sed 's/ github/ github/i' > $rand git -C "$CURLWWW" log --use-mailmap "$start..HEAD" fi } | \ - grep -Eai '(^Author|^Commit|by):' | \ + grep -Eai '(^Author|^Commit|^ +[a-z-]+-by):' | \ cut -d: -f2- | \ cut '-d(' -f1 | \ cut '-d<' -f1 | \ diff --git a/scripts/delta b/scripts/delta index b6a1df8a17e2..c67d98a2c3d4 100755 --- a/scripts/delta +++ b/scripts/delta @@ -95,7 +95,7 @@ my $deletes=`git diff-tree --diff-filter=A -r --summary origin/$branch $start 2> my $creates=`git diff-tree --diff-filter=D -r --summary origin/$branch $start 2>/dev/null | wc -l`; # Time since that tag -my $tagged=`git for-each-ref --format="%(refname:short) | %(taggerdate:unix)" refs/tags/* | grep ^$start | cut "-d|" -f2`; # Unix timestamp +my $tagged=`git for-each-ref --format="%(refname:short) | %(taggerdate:unix)" refs/tags/* | grep ^$start | cut '-d|' -f2`; # Unix timestamp my $taggednice=`git for-each-ref --format="%(refname:short) | %(creatordate)" refs/tags/* | grep ^$start | cut '-d|' -f2`; # human readable time chomp $taggednice; my $now=POSIX::strftime("%s", localtime()); diff --git a/scripts/firefox-db2pem.sh b/scripts/firefox-db2pem.sh index 634e429b504f..7d31b1288693 100755 --- a/scripts/firefox-db2pem.sh +++ b/scripts/firefox-db2pem.sh @@ -54,7 +54,6 @@ cat > "$out" < out.tar.gz mv out.tar.gz ../ cd .. diff --git a/scripts/managen b/scripts/managen index 0c75148fd170..a537e3843200 100755 --- a/scripts/managen +++ b/scripts/managen @@ -25,7 +25,7 @@ =begin comment -This script generates the manpage. +This script generates the man page. Example: managen [files] > curl.1 @@ -64,7 +64,7 @@ my $globals; my $error = 0; my $indent = 4; -# get the long name version, return the manpage string +# get the long name version, return the man page string sub manpageify { my ($k, $manpage)=@_; my $trail = ''; @@ -85,7 +85,6 @@ sub manpageify { return "--$k$trail"; } - my $colwidth=79; # max number of columns sub prefixline { @@ -412,7 +411,7 @@ sub render { print STDERR "$f:$line:1:WARN: un-escaped < or > used: $nontick\n"; } - # if there is a space, it needs quotes for manpage + # if there is a space, it needs quotes for man page if(($word =~ / /) && $manpage) { $word = "\"$word\""; } @@ -500,7 +499,6 @@ sub render { # convert single backslash to double-backslash $d =~ s/\\/\\\\/g if($manpage); - if($manpage) { if(!$quote && $d =~ /--/) { $d =~ s/--([a-z0-9.-]+)/manpageify($1, 1)/ge; @@ -538,7 +536,7 @@ sub render { exit 3; } if($quote) { - # don't leave the quote "hanging" + # do not leave the quote "hanging" push @desc, ".fi\n" if($manpage); } if($tablemode) { @@ -854,7 +852,7 @@ sub single { if($requires) { my $l = manpageify($long, $manpage); - push @foot, "$l requires that libcurl". + push @foot, "For $l to work, it requires that the underlying libcurl". " is built to support $requires.\n"; } if($mutexed) { @@ -1047,12 +1045,11 @@ sub header { printdesc($manpage, 0, @d); } - sub sourcecategories { my ($dir) = @_; my %cats; open(H, "<$dir/../../src/tool_help.h") || - die "can't find the header file"; + die "cannot find the header file"; while() { if(/^\#define CURLHELP_([A-Z0-9]*)/) { $cats{lc($1)}++; @@ -1130,7 +1127,7 @@ HEAD $bitmask .= ' | '; } } - $bitmask =~ s/(?=.{76}).{1,76}\|/$&\n /g; + $bitmask =~ s/(?=.{76}).{1,76}\|/$&\n /g; my $arg = $arglong{$long}; if($arg) { $opt .= " $arg"; @@ -1138,7 +1135,7 @@ HEAD my $desc = $helplong{$f}; $desc =~ s/\"/\\\"/g; # escape double quotes - my $line = sprintf " {\"%s\",\n \"%s\",\n %s},\n", $opt, $desc, $bitmask; + my $line = sprintf " { \"%s\",\n \"%s\",\n %s },\n", $opt, $desc, $bitmask; if(length($opt) > 78) { print STDERR "WARN: the --$long name is too long\n"; @@ -1253,7 +1250,7 @@ sub mainpage { .\\" * .\\" ************************************************************************** .\\" -.\\" DO NOT EDIT. Generated by the curl project managen manpage generator. +.\\" DO NOT EDIT. Generated by the curl project managen man page generator. .\\" .TH curl 1 "$date" "curl $version" "curl Manual" HEADER diff --git a/scripts/mdlinkcheck b/scripts/mdlinkcheck index bbd6ac46022b..4ee0b537525a 100755 --- a/scripts/mdlinkcheck +++ b/scripts/mdlinkcheck @@ -27,7 +27,10 @@ use strict; use warnings; my %whitelist = ( + 'https://curl.se' => 1, 'https://curl.se/' => 1, + 'https://curl.se/bug/' => 1, + 'https://curl.se/bug/view.cgi' => 1, 'https://curl.se/changes.html' => 1, 'https://curl.se/dev/advisory.html' => 1, 'https://curl.se/dev/builds.html' => 1, @@ -40,19 +43,25 @@ my %whitelist = ( 'https://curl.se/docs/bugbounty.html' => 1, 'https://curl.se/docs/caextract.html' => 1, 'https://curl.se/docs/copyright.html' => 1, + 'https://curl.se/docs/http-cookies.html' => 1, 'https://curl.se/docs/install.html' => 1, 'https://curl.se/docs/knownbugs.html' => 1, 'https://curl.se/docs/manpage.html' => 1, + 'https://curl.se/docs/releases.html' => 1, 'https://curl.se/docs/security.html' => 1, + 'https://curl.se/docs/ssl-ciphers.html' => 1, + 'https://curl.se/docs/ssl-compared.html' => 1, 'https://curl.se/docs/sslcerts.html' => 1, 'https://curl.se/docs/thanks.html' => 1, 'https://curl.se/docs/todo.html' => 1, 'https://curl.se/docs/vulnerabilities.html' => 1, + 'https://curl.se/download.html' => 1, 'https://curl.se/libcurl/' => 1, - 'https://curl.se/libcurl/c/CURLOPT_SSLVERSION.html' => 1, 'https://curl.se/libcurl/c/CURLOPT_SSL_CIPHER_LIST.html' => 1, + 'https://curl.se/libcurl/c/CURLOPT_SSLVERSION.html' => 1, 'https://curl.se/libcurl/c/CURLOPT_TLS13_CIPHERS.html' => 1, 'https://curl.se/libcurl/c/libcurl.html' => 1, + 'https://curl.se/libcurl/c/threadsafe.html' => 1, 'https://curl.se/logo/curl-logo.svg' => 1, 'https://curl.se/mail/' => 1, 'https://curl.se/mail/etiquette.html' => 1, @@ -62,22 +71,27 @@ my %whitelist = ( 'https://curl.se/rfc/rfc2255.txt' => 1, 'https://curl.se/sponsors.html' => 1, 'https://curl.se/support.html' => 1, + 'https://curl.se/windows/' => 1, + + 'https://testclutch.curl.se/' => 1, - 'https://github.com/curl/curl' => 1, 'https://github.com/curl/curl-fuzzer' => 1, 'https://github.com/curl/curl-www' => 1, - 'https://github.com/curl/curl/discussions' => 1, - 'https://github.com/curl/curl/issues' => 1, - 'https://github.com/curl/curl/labels/help%20wanted' => 1, - 'https://github.com/curl/curl/pulls' => 1, + 'https://github.com/curl/curl/wcurl' => 1, ); my %url; my %flink; -# list all .md files in the repo -my @files=`git ls-files '**.md'`; +my $dry; +if(defined $ARGV[0] && $ARGV[0] eq "--dry-run") { + $dry = 1; + shift @ARGV; +} + +# list all files to scan for links +my @files=`git ls-files docs include lib scripts src`; sub storelink { my ($f, $line, $link) = @_; @@ -91,7 +105,33 @@ sub storelink { $link =~ s:\#.*\z::; if($link =~ /^(https|http):/) { - $url{$link} .= "$f:$line "; + if($whitelist{$link}) { + #print "-- whitelisted: $link\n"; + $whitelist{$link}++; + } + # example.com is just example + elsif($link =~ /^https:\/\/(.*)example.(com|org|net)/) { + #print "-- example: $link\n"; + } + # so is using the .example TLD + elsif($link =~ /^https:\/\/(.*)\.example(\/|$|:)/) { + #print "-- .example: $link\n"; + } + # so is using anything on localhost + elsif($link =~ /^http(s|):\/\/localhost/) { + #print "-- localhost: $link\n"; + } + # ignore all links to curl's github repo + elsif($link =~ /^https:\/\/github.com\/curl\/curl(\/|$)/) { + #print "-- curl github repo: $link\n"; + } + elsif($link =~ /^(https|http):\/\/[0-9.]+(\/|$)/) { + #print "-- IPv4 number: $link\n"; + } + else { + #print "ADD '$link'\n"; + $url{$link} .= "$f:$line "; + } return; } @@ -118,12 +158,23 @@ sub findlinks { open(F, "<:crlf", "$f") || return; + # is it a markdown extension? + my $md = ($f =~ /\.md$/i); + while() { - if(/\]\(([^)]*)/) { + chomp; + if($md && /\]\(([^)]*)/) { my $link = $1; #print "$f:$line $link\n"; storelink($f, $line, $link); } + # ignore trailing: dot, double quote, single quote, asterisk, hash, + # comma, question mark, colon, closing parenthesis, backslash, + # closing angle bracket, whitespace, pipe, backtick, semicolon + elsif(/(https:\/\/[a-z0-9.\/:%_+@-]+[^."'*\#,?:\)> \t|`;\\])/i) { + #print "RAW '$_'\n"; + storelink($f, $line, $1); + } $line++; } close(F); @@ -133,38 +184,53 @@ sub checkurl { my ($url) = @_; if($whitelist{$url}) { - #print "$url is whitelisted\n"; + #print STDERR "$url is whitelisted\n"; return 0; } - print "check $url\n"; - my $curlcmd="curl -ILfsm10 --retry 2 --retry-delay 5 -A \"Mozilla/curl.se link-probe\""; $url =~ s/\+/%2B/g; - if($url =~ /[\"\'\n]/) { - print STDERR "Bad URL in markdown: %s\n", $url{$url}; - return 1; # fail + my @content; + if(open(my $fh, '-|', 'curl', '-ILfsm10', '--retry', '2', '--retry-delay', '5', + '-A', 'Mozilla/curl.se link-probe', $url)) { + @content = <$fh>; + close $fh; } - my @content = `$curlcmd \"$url\"`; if(!$content[0]) { - print STDERR "FAIL\n"; + print "FAIL: $url\n"; return 1; # fail } + print "OK: $url\n"; return 0; # ok } for my $f (@files) { chomp $f; - findlinks($f); + if($f !~ /\/mdlinkcheck$/) { + findlinks($f); + } } -my $error; +for my $u (sort keys %whitelist) { + if($whitelist{$u} == 1) { + printf STDERR "warning: unused whitelist entry: '$u'\n"; + } +} +if($dry) { + for my $u (sort keys %url) { + print "$u\n"; + } + exit; +} + +my $error; +my @errlist; for my $u (sort keys %url) { my $r = checkurl($u); if($r) { for my $f (split(/ /, $url{$u})) { - printf "%s ERROR links to missing URL %s\n", $f, $u; + push @errlist, sprintf "%s ERROR links to missing URL %s\n", $f, $u; $error++; } } @@ -173,10 +239,17 @@ for my $u (sort keys %url) { for my $l (sort keys %flink) { if(! -r $l) { for my $f (split(/ /, $flink{$l})) { - printf "%s ERROR links to missing file %s\n", $f, $l; + push @errlist, sprintf "%s ERROR links to missing file %s\n", $f, $l; $error++; } } } +printf "Checked %d URLs\n", scalar(keys %url); +if($error) { + print "$error URLs had problems:\n"; + for(@errlist) { + print $_; + } +} exit 1 if($error); diff --git a/scripts/mk-ca-bundle.pl b/scripts/mk-ca-bundle.pl index cb0b58609326..923af1eb55f6 100755 --- a/scripts/mk-ca-bundle.pl +++ b/scripts/mk-ca-bundle.pl @@ -60,7 +60,7 @@ # If the OpenSSL commandline is not in search path you can configure it here! my $openssl = 'openssl'; -my $version = '1.29'; +my $version = '1.30'; $opt_w = 76; # default base64 encoded lines length @@ -91,8 +91,8 @@ my @valid_mozilla_trust_levels = ( "TRUSTED_DELEGATOR", # CAs - "NOT_TRUSTED", # Don't trust these certs. - "MUST_VERIFY_TRUST", # This explicitly tells us that it ISN'T a CA but is + "NOT_TRUSTED", # Do not trust these certs. + "MUST_VERIFY_TRUST", # This explicitly tells us that it IS NOT a CA but is # otherwise ok. In other words, this should tell the # app to ignore any other sources that claim this is # a CA. @@ -100,7 +100,7 @@ # for delegates (i.e. it is not a CA). ); -my $default_signature_algorithms = $opt_s = "MD5"; +my $default_signature_algorithms = $opt_s = "SHA256"; my @valid_signature_algorithms = ( "MD5", @@ -154,7 +154,7 @@ () print " 2) Default to 'release', but more recent updates may be found in other trees\n"; print " 3) certdata.txt file format may change, lag time to update this script\n"; print " 4) Generally unwise to blindly trust CAs without manual review & verification\n"; - print " 5) Mozilla apps use additional security checks aren't represented in certdata\n"; + print " 5) Mozilla apps use additional security checks are not represented in certdata\n"; print " 6) Use of this script will make a security engineer grind his teeth and\n"; print " swear at you. ;)\n"; exit; @@ -241,19 +241,20 @@ ($$@) sub sha256 { my $result; if($Digest::SHA::VERSION || $Digest::SHA::PurePerl::VERSION) { - open(FILE, $_[0]) or die "Can't open '$_[0]': $!"; + open(FILE, $_[0]) or die "Could not open '$_[0]': $!"; binmode(FILE); $result = $MOD_SHA->new(256)->addfile(*FILE)->hexdigest; close(FILE); } else { # Use OpenSSL command if Perl Digest::SHA modules not available - $result = `"$openssl" dgst -r -sha256 "$_[0]"`; + open(my $fh, '-|', $openssl, 'dgst', '-r', '-sha256', $_[0]) or die "Failed running openssl on '$_[0]': $!"; + $result = <$fh>; # read first line + close $fh; $result =~ s/^([0-9a-f]{64}) .+/$1/is; } return $result; } - sub oldhash { my $hash = ""; open(C, "<$_[0]") || return 0; @@ -311,10 +312,16 @@ (%) if($curl) { if($curl =~ /^Protocols:.* https( |$)/m) { report "Get certdata with curl!"; - my $proto = !$opt_k ? "--proto =https" : ""; - my $quiet = $opt_q ? "-s" : ""; - my @out = `curl -Lw %{response_code} $proto $quiet -o "$txt" "$url"`; - if(!$? && @out && $out[0] == 200) { + my @opts = (); + push @opts, '--proto', '=https' if !$opt_k; + push @opts, '-s' if $opt_q; + my $out = ''; + if(open(my $fh, '-|', 'curl', '-Lw', '%{response_code}', (@opts), '-o', $txt, $url)) { + $out = <$fh>; # read first line + chomp $out; + close $fh; + } + if($out && $out == 200) { $fetched = 1; report "Downloaded $txt"; } @@ -349,7 +356,7 @@ (%) report "LWP is not available (LWP::UserAgent not found)"; exit 1; } - my $ua = new LWP::UserAgent(agent => "$0/$version"); + my $ua = new LWP::UserAgent(agent => "$0/$version"); $ua->env_proxy(); $resp = $ua->mirror($url, $txt); if($resp && $resp->code eq '304') { @@ -393,9 +400,9 @@ (%) my $format = $opt_t ? "plain text and " : ""; if($stdout) { - open(CRT, '> -') or die "Couldn't open STDOUT: $!\n"; + open(CRT, '> -') or die "Could not open STDOUT: $!\n"; } else { - open(CRT,">$crt.~") or die "Couldn't open $crt.~: $!\n"; + open(CRT,">$crt.~") or die "Could not open $crt.~: $!\n"; } print CRT <) { if(/\*\*\*\*\* BEGIN LICENSE BLOCK \*\*\*\*\*/) { print CRT; @@ -621,25 +628,25 @@ (%) $pipe = "|$openssl x509 -" . $hash . " -fingerprint -noout -inform PEM"; if(!$stdout) { $pipe .= " >> $crt.~"; - close(CRT) or die "Couldn't close $crt.~: $!"; + close(CRT) or die "Could not close $crt.~: $!"; } - open(TMP, $pipe) or die "Couldn't open openssl pipe: $!"; + open(TMP, $pipe) or die "Could not open openssl pipe: $!"; print TMP $pem; - close(TMP) or die "Couldn't close openssl pipe: $!"; + close(TMP) or die "Could not close openssl pipe: $!"; if(!$stdout) { - open(CRT, ">>$crt.~") or die "Couldn't open $crt.~: $!"; + open(CRT, ">>$crt.~") or die "Could not open $crt.~: $!"; } } $pipe = "|$openssl x509 -text -inform PEM"; if(!$stdout) { $pipe .= " >> $crt.~"; - close(CRT) or die "Couldn't close $crt.~: $!"; + close(CRT) or die "Could not close $crt.~: $!"; } - open(TMP, $pipe) or die "Couldn't open openssl pipe: $!"; + open(TMP, $pipe) or die "Could not open openssl pipe: $!"; print TMP $pem; - close(TMP) or die "Couldn't close openssl pipe: $!"; + close(TMP) or die "Could not close openssl pipe: $!"; if(!$stdout) { - open(CRT, ">>$crt.~") or die "Couldn't open $crt.~: $!"; + open(CRT, ">>$crt.~") or die "Could not open $crt.~: $!"; } } report "Processed: $caname" if($opt_v); @@ -647,8 +654,8 @@ (%) } } } -close(TXT) or die "Couldn't close $txt: $!\n"; -close(CRT) or die "Couldn't close $crt.~: $!\n"; +close(TXT) or die "Could not close $txt: $!\n"; +close(CRT) or die "Could not close $crt.~: $!\n"; unless($stdout) { if($opt_b && -e $crt) { my $bk = 1; diff --git a/scripts/perlcheck.sh b/scripts/perlcheck.sh index 7ec23983d5e6..c243f50271c5 100755 --- a/scripts/perlcheck.sh +++ b/scripts/perlcheck.sh @@ -23,7 +23,7 @@ # ########################################################################### -# The xargs invocation is portable, but does not preserve spaces in file names. +# The xargs invocation is portable, but does not preserve spaces in filenames. # If such a file is ever added, then this can be portably fixed by switching to # "xargs -I{}" and appending {} to the end of the xargs arguments (which will # call cmakelint once per file) or by using the GNU extension "xargs -d'\n'". @@ -38,14 +38,11 @@ echo "parallel: ${procs}" { if [ -n "${1:-}" ]; then - for A in "$@"; do printf "%s\n" "$A"; done + for A in "$@"; do printf '%s\n' "$A"; done elif git rev-parse --is-inside-work-tree >/dev/null 2>&1; then - { - git ls-files | grep -E '\.(pl|pm)$' - git grep -l -E '^#!/usr/bin/env perl' - } | sort -u + git ls-files '*.pl' '*.pm' + git grep -l '^#!/usr/bin/env perl' else - # strip off the leading ./ to make the grep regexes work properly - find . -type f \( -name '*.pl' -o -name '*.pm' \) | sed 's@^\./@@' + find . -type f \( -name '*.pl' -o -name '*.pm' \) fi -} | xargs -n 1 -P "${procs}" perl -c -Itests -- +} | sort -u | xargs -n 1 -P "${procs}" perl -c -Itests -- diff --git a/scripts/release-notes.pl b/scripts/release-notes.pl index 593d7965a308..a4b4e2550fa0 100755 --- a/scripts/release-notes.pl +++ b/scripts/release-notes.pl @@ -31,10 +31,10 @@ # # $ ./scripts/release-notes.pl # -# 2. Edit RELEASE-NOTES and remove all entries that don't belong. Unused +# 2. Edit RELEASE-NOTES and remove all entries that do not belong. Unused # references below will be cleaned up in the next step. Make sure to move # "changes" up to the changes section. All entries will by default be listed -# under bug-fixes as this script can't know where to put them. +# under bug-fixes as this script cannot know where to put them. # # 3. Run the cleanup script and let it sort the entries and remove unused # references from lines you removed in step (2): diff --git a/scripts/release-tools.sh b/scripts/release-tools.sh index 4c4ed7d8097d..fc5d87fb9004 100755 --- a/scripts/release-tools.sh +++ b/scripts/release-tools.sh @@ -31,7 +31,7 @@ version=${2:-unknown} tag=$(echo "curl-$version" | tr '.' '_') commit=${3} if [ -n "$commit" ] && [ -r "docs/tarball-commit.txt.dist" ]; then - # If commit is given, then the tag likely doesn't actually exist + # If commit is given, then the tag likely does not actually exist tag="$(cat docs/tarball-commit.txt.dist)" fi diff --git a/scripts/schemetable.c b/scripts/schemetable.c index e65c462f7b36..2c1c3c0548fe 100644 --- a/scripts/schemetable.c +++ b/scripts/schemetable.c @@ -35,45 +35,45 @@ struct detail { }; 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", "#ifdef USE_SSH" }, - {"sftp", "#ifdef USE_SSH" }, - {"smb", "#if !defined(CURL_DISABLE_SMB) && \\\n" - " defined(USE_CURL_NTLM_CORE) && (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(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)" }, - {"wss", "#if !defined(CURL_DISABLE_WEBSOCKETS) && \\\n" - " defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)" }, + { "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", "#ifdef USE_SSH" }, + { "sftp", "#ifdef USE_SSH" }, + { "smb", "#if !defined(CURL_DISABLE_SMB) && \\\n" + " defined(USE_CURL_NTLM_CORE) && (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(CURL_DISABLE_WEBSOCKETS) && !defined(CURL_DISABLE_HTTP)" }, + { "wss", "#if !defined(CURL_DISABLE_WEBSOCKETS) && \\\n" + " defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)" }, { NULL, NULL } }; @@ -108,7 +108,8 @@ static void showtable(int try, int init, int shift) " s++;\n" " l--;\n" " }\n" - "*/\n", init, shift); + "*/\n", + init, shift); printf(" static const struct Curl_handler * const protocols[%d] = {", try); @@ -158,10 +159,10 @@ int main(void) for(j = 0; j < i; j++) { if(num[j] == v) { - /* +#if 0 printf("NOPE: %u is a dupe (%s and %s)\n", v, scheme[i], scheme[j]); - */ +#endif badcombo = 1; break; } diff --git a/scripts/singleuse.pl b/scripts/singleuse.pl index b4cbe3ff4a12..3ce5dda4423b 100755 --- a/scripts/singleuse.pl +++ b/scripts/singleuse.pl @@ -36,7 +36,7 @@ use strict; use warnings; -my $unittests; +my $unittests=""; if(@ARGV && $ARGV[0] eq "--unit") { $unittests = "tests/unit "; shift @ARGV; diff --git a/scripts/top-complexity b/scripts/top-complexity index 414adaf56ca7..cd132697f7a9 100755 --- a/scripts/top-complexity +++ b/scripts/top-complexity @@ -64,7 +64,7 @@ open(F, "git ls-files '*.c'|"); while() { chomp $_; my $file = $_; - # we can't filter these with git so do it here + # we cannot filter these with git so do it here if($file =~ /^(lib|src)/) { push @files, $file; } diff --git a/scripts/verify-release b/scripts/verify-release index 2f7a0bf89fea..b24d9b370d5a 100755 --- a/scripts/verify-release +++ b/scripts/verify-release @@ -40,12 +40,7 @@ if [ -z "$tarball" ]; then exit fi -i="0" - -# shellcheck disable=SC2034 -for dl in curl-*; do - i=$((i + 1)) -done +i="$(find . -maxdepth 1 -type d -name 'curl-*' | wc -l)" if test "$i" -gt 1; then echo "multiple curl-* entries found, disambiguate please" diff --git a/scripts/wcurl b/scripts/wcurl index 1014779e131b..cbdbb327e4e9 100755 --- a/scripts/wcurl +++ b/scripts/wcurl @@ -29,7 +29,7 @@ # Stop on errors and on usage of unset variables. set -eu -VERSION="2025.09.27" +VERSION="2025.11.09" PROGRAM_NAME="$(basename "$0")" readonly PROGRAM_NAME @@ -65,7 +65,7 @@ Options: multiple times, only the last value is considered. --no-decode-filename: Don't percent-decode the output filename, even if the percent-encoding in - the URL was done by wcurl, e.g.: The URL contained whitespaces. + the URL was done by wcurl, e.g.: The URL contained whitespace. --dry-run: Don't actually execute curl, just print what would be invoked. @@ -77,7 +77,7 @@ Options: instead forwarded to the curl invocation. : URL to be downloaded. Anything that is not a parameter is considered - an URL. Whitespaces are percent-encoded and the URL is passed to curl, which + an URL. Whitespace is percent-encoded and the URL is passed to curl, which then performs the parsing. May be specified more than once. _EOF_ } @@ -85,7 +85,7 @@ _EOF_ # Display an error message and bail out. error() { - printf "%s\n" "$*" > /dev/stderr + printf "%s\n" "$*" >&2 exit 1 } @@ -113,6 +113,13 @@ readonly PER_URL_PARAMETERS="\ --remote-time \ --retry 5 " +# Valid percent-encode codes that are considered unsafe to be decoded. +# This is a list of space-separated percent-encoded uppercase +# characters. +# 2F = / +# 5C = \ +readonly UNSAFE_PERCENT_ENCODE="%2F %5C" + # Whether to invoke curl or not. DRY_RUN="false" @@ -137,6 +144,20 @@ is_subset_of() esac } +# Indicate via exit code whether the HTML code given in the first +# parameter is safe to be decoded. +is_safe_percent_encode() +{ + upper_str=$(printf "%s" "${1}" | tr "[:lower:]" "[:upper:]") + for unsafe in ${UNSAFE_PERCENT_ENCODE}; do + if [ "${unsafe}" = "${upper_str}" ]; then + return 1 + fi + done + + return 0 +} + # Print the given string percent-decoded. percent_decode() { @@ -151,9 +172,10 @@ percent_decode() decode_out="${decode_out}${decode_hex2}" # Skip decoding if this is a control character (00-1F). # Skip decoding if DECODE_FILENAME is not "true". - if is_subset_of "${decode_hex1}" "23456789abcdefABCDEF" \ + if [ "${DECODE_FILENAME}" = "true" ] \ + && is_subset_of "${decode_hex1}" "23456789abcdefABCDEF" \ && is_subset_of "${decode_hex2}" "0123456789abcdefABCDEF" \ - && [ "${DECODE_FILENAME}" = "true" ]; then + && is_safe_percent_encode "${decode_out}"; then # Use printf to decode it into octal and then decode it to the final format. decode_out="$(printf "%b" "\\$(printf %o "0x${decode_hex1}${decode_hex2}")")" fi @@ -301,7 +323,7 @@ while [ -n "${1-}" ]; do # This is the start of the list of URLs. shift for url in "$@"; do - # Encode whitespaces into %20, since wget supports those URLs. + # Encode whitespace into %20, since wget supports those URLs. newurl=$(printf "%s\n" "${url}" | sed 's/ /%20/g') URLS="${URLS} ${newurl}" done @@ -314,7 +336,7 @@ while [ -n "${1-}" ]; do *) # This must be a URL. - # Encode whitespaces into %20, since wget supports those URLs. + # Encode whitespace into %20, since wget supports those URLs. newurl=$(printf "%s\n" "${1}" | sed 's/ /%20/g') URLS="${URLS} ${newurl}" ;; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a70c96b7650f..6d3d6e3d4861 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -28,8 +28,8 @@ set(_curl_cfiles_gen "") set(_curl_hfiles_gen "") set(_curl_definitions "") -if(ENABLE_CURL_MANUAL AND (PERL_FOUND OR EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tool_hugehelp.c")) - if(PERL_FOUND) +if(ENABLE_CURL_MANUAL AND (Perl_FOUND OR EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tool_hugehelp.c")) + if(Perl_FOUND) add_custom_command(OUTPUT "tool_hugehelp.c" COMMAND ${CMAKE_COMMAND} -E echo "#include \"tool_setup.h\"" > "tool_hugehelp.c" COMMAND ${CMAKE_COMMAND} -E echo "/* !checksrc! disable COPYRIGHT all */" >> "tool_hugehelp.c" @@ -55,7 +55,7 @@ if(ENABLE_CURL_MANUAL AND (PERL_FOUND OR EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/too endif() if(CURL_CA_EMBED_SET) - if(PERL_FOUND) + if(Perl_FOUND) add_custom_command(OUTPUT "tool_ca_embed.c" COMMAND "${PERL_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/mk-file-embed.pl" --var curl_ca_embed < "${CURL_CA_EMBED}" > "tool_ca_embed.c" @@ -109,19 +109,20 @@ target_link_libraries(${EXE_NAME} ${LIB_SELECTED_FOR_EXE} ${CURL_LIBS}) add_executable(${PROJECT_NAME}::${EXE_NAME} ALIAS ${EXE_NAME}) add_executable(curlinfo EXCLUDE_FROM_ALL "curlinfo.c") +target_link_libraries(curlinfo PRIVATE ${CURL_LIBS}) set_target_properties(curlinfo PROPERTIES UNITY_BUILD OFF) # special libcurltool library just for unittests add_library(curltool STATIC EXCLUDE_FROM_ALL ${CURL_CFILES} ${CURL_HFILES} ${_curlx_cfiles_lib} ${_curlx_hfiles_lib}) target_compile_definitions(curltool PUBLIC "CURL_STATICLIB" "UNITTESTS") -target_link_libraries(curltool PRIVATE ${CURL_LIBS}) +target_link_libraries(curltool PUBLIC ${CURL_LIBS}) set_target_properties(curltool PROPERTIES C_CLANG_TIDY "") if(CURL_HAS_LTO) set_target_properties(${EXE_NAME} PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) endif() -if(ENABLE_UNICODE AND MINGW AND NOT MINGW32CE) +if(ENABLE_UNICODE AND MINGW) if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.13) set_property(TARGET ${EXE_NAME} APPEND PROPERTY LINK_OPTIONS "-municode") else() @@ -141,8 +142,13 @@ endif() ################################################################################ -install(TARGETS ${EXE_NAME} EXPORT ${TARGETS_EXPORT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR}) -export(TARGETS ${EXE_NAME} - FILE "${PROJECT_BINARY_DIR}/curl-target.cmake" - NAMESPACE ${PROJECT_NAME}:: -) +if(CURL_ENABLE_EXPORT_TARGET) + if(NOT CURL_DISABLE_INSTALL) + install(TARGETS ${EXE_NAME} EXPORT ${TARGETS_EXPORT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR}) + endif() + + export(TARGETS ${EXE_NAME} + FILE "${PROJECT_BINARY_DIR}/curl-target.cmake" + NAMESPACE ${PROJECT_NAME}:: + ) +endif() diff --git a/src/Makefile.am b/src/Makefile.am index c1bcf273597e..169a64f71391 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -61,7 +61,6 @@ if CURLDEBUG AM_CPPFLAGS += -DCURLDEBUG endif -AM_LDFLAGS = if USE_UNICODE UNICODEFLAG = -municode endif @@ -94,7 +93,7 @@ curl_SOURCES += $(CURL_RCFILES) $(CURL_RCFILES): tool_version.h endif -curl_LDFLAGS = $(AM_LDFLAGS) $(CURL_LDFLAGS_BIN) $(UNICODEFLAG) +curl_LDFLAGS = $(CURL_LDFLAGS_BIN) $(UNICODEFLAG) # This might hold -Werror CFLAGS += @CURL_CFLAG_EXTRAS@ diff --git a/src/Makefile.inc b/src/Makefile.inc index fa5583755203..4e8efdd9265b 100644 --- a/src/Makefile.inc +++ b/src/Makefile.inc @@ -38,6 +38,7 @@ CURLX_CFILES = \ ../lib/curlx/fopen.c \ ../lib/curlx/multibyte.c \ ../lib/curlx/nonblock.c \ + ../lib/curlx/strcopy.c \ ../lib/curlx/strerr.c \ ../lib/curlx/strparse.c \ ../lib/curlx/timediff.c \ @@ -54,6 +55,8 @@ CURLX_HFILES = \ ../lib/curlx/fopen.h \ ../lib/curlx/multibyte.h \ ../lib/curlx/nonblock.h \ + ../lib/curlx/snprintf.h \ + ../lib/curlx/strcopy.h \ ../lib/curlx/strerr.h \ ../lib/curlx/strparse.h \ ../lib/curlx/timediff.h \ @@ -63,6 +66,12 @@ CURLX_HFILES = \ ../lib/curlx/warnless.h \ ../lib/curlx/winapi.h +TOOLX_CFILES = \ + toolx/tool_time.c + +TOOLX_HFILES = \ + toolx/tool_time.h + CURL_CFILES = \ config2setopts.c \ slist_wc.c \ @@ -106,7 +115,8 @@ CURL_CFILES = \ tool_writeout.c \ tool_writeout_json.c \ tool_xattr.c \ - var.c + var.c \ + $(TOOLX_CFILES) CURL_HFILES = \ config2setopts.h \ @@ -153,6 +163,7 @@ CURL_HFILES = \ tool_writeout.h \ tool_writeout_json.h \ tool_xattr.h \ - var.h + var.h \ + $(TOOLX_HFILES) CURL_RCFILES = curl.rc diff --git a/src/config2setopts.c b/src/config2setopts.c index c367959ccb3e..89a003cc96ac 100644 --- a/src/config2setopts.c +++ b/src/config2setopts.c @@ -37,6 +37,7 @@ #include "tool_cb_see.h" #include "tool_cb_dbg.h" #include "tool_helpers.h" +#include "tool_version.h" #define BUFFER_SIZE 102400L @@ -137,30 +138,36 @@ static CURLcode url_proto_and_rewrite(char **url, DEBUGASSERT(url && *url); if(uh) { char *schemep = NULL; - if(!curl_url_set(uh, CURLUPART_URL, *url, - CURLU_GUESS_SCHEME | CURLU_NON_SUPPORT_SCHEME) && - !curl_url_get(uh, CURLUPART_SCHEME, &schemep, - CURLU_DEFAULT_SCHEME)) { + CURLUcode uc = + curl_url_set(uh, CURLUPART_URL, *url, + CURLU_GUESS_SCHEME | CURLU_NON_SUPPORT_SCHEME); + if(!uc) { + uc = curl_url_get(uh, CURLUPART_SCHEME, &schemep, CURLU_DEFAULT_SCHEME); + if(!uc) { #ifdef CURL_DISABLE_IPFS - (void)config; + (void)config; #else - 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 is 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 + 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 is 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 #endif /* !CURL_DISABLE_IPFS */ - proto = proto_token(schemep); - - curl_free(schemep); + proto = proto_token(schemep); + curl_free(schemep); + } + else if(uc == CURLUE_OUT_OF_MEMORY) + result = CURLE_OUT_OF_MEMORY; } + else if(uc == CURLUE_OUT_OF_MEMORY) + result = CURLE_OUT_OF_MEMORY; curl_url_cleanup(uh); } else @@ -175,32 +182,26 @@ static CURLcode ssh_setopts(struct OperationConfig *config, CURL *curl) CURLcode result; /* SSH and SSL private key uses same command-line option */ - /* new in libcurl 7.16.1 */ - my_setopt_str(curl, CURLOPT_SSH_PRIVATE_KEYFILE, config->key); - /* new in libcurl 7.16.1 */ - my_setopt_str(curl, CURLOPT_SSH_PUBLIC_KEYFILE, config->pubkey); - - /* new in libcurl 7.17.1: SSH host key md5 checking allows us - to fail if we are not talking to who we think we should */ - my_setopt_str(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_MD5, - config->hostpubmd5); - - /* new in libcurl 7.80.0: SSH host key sha256 checking allows us - to fail if we are not talking to who we think we should */ - my_setopt_str(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256, + MY_SETOPT_STR(curl, CURLOPT_SSH_PRIVATE_KEYFILE, config->key); + MY_SETOPT_STR(curl, CURLOPT_SSH_PUBLIC_KEYFILE, config->pubkey); + + /* SSH host key md5 checking allows us to fail if we are not talking to who + we think we should */ + MY_SETOPT_STR(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_MD5, config->hostpubmd5); + + /* SSH host key sha256 checking allows us to fail if we are not talking to + who we think we should */ + MY_SETOPT_STR(curl, CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256, config->hostpubsha256); - /* new in libcurl 7.56.0 */ if(config->ssh_compression) my_setopt_long(curl, CURLOPT_SSH_COMPRESSION, 1); if(!config->insecure_ok) { char *known = config->knownhosts; - if(!known) known = findfile(".ssh/known_hosts", FALSE); if(known) { - /* new in curl 7.19.6 */ result = my_setopt_str(curl, CURLOPT_SSH_KNOWNHOSTS, known); if(result) { config->knownhosts = NULL; @@ -211,11 +212,11 @@ static CURLcode ssh_setopts(struct OperationConfig *config, CURL *curl) config->knownhosts = known; } else if(!config->hostpubmd5 && !config->hostpubsha256) { - errorf("Couldn't find a known_hosts file"); + errorf("Could not find a known_hosts file"); return CURLE_FAILED_INIT; } else - warnf("Couldn't find a known_hosts file"); + warnf("Could not find a known_hosts file"); } return CURLE_OK; /* ignore if SHA256 did not work */ } @@ -280,32 +281,26 @@ static CURLcode ssl_setopts(struct OperationConfig *config, CURL *curl) CURLcode result = CURLE_OK; if(config->cacert) - my_setopt_str(curl, CURLOPT_CAINFO, config->cacert); + MY_SETOPT_STR(curl, CURLOPT_CAINFO, config->cacert); if(config->proxy_cacert) - my_setopt_str(curl, CURLOPT_PROXY_CAINFO, config->proxy_cacert); + MY_SETOPT_STR(curl, CURLOPT_PROXY_CAINFO, config->proxy_cacert); + if(config->capath) + MY_SETOPT_STR(curl, CURLOPT_CAPATH, config->capath); - if(config->capath) { - result = my_setopt_str(curl, CURLOPT_CAPATH, config->capath); - if(result) - return result; - } /* For the time being if --proxy-capath is not set then we use the --capath value for it, if any. See #1257 */ if(config->proxy_capath || config->capath) { - result = my_setopt_str(curl, CURLOPT_PROXY_CAPATH, - (config->proxy_capath ? config->proxy_capath : - config->capath)); - if((result == CURLE_NOT_BUILT_IN) || - (result == CURLE_UNKNOWN_OPTION)) { - if(config->proxy_capath) { - warnf("ignoring %s, not supported by libcurl with %s", - config->proxy_capath ? "--proxy-capath" : "--capath", - ssl_backend()); - } + MY_SETOPT_STR(curl, CURLOPT_PROXY_CAPATH, + (config->proxy_capath ? config->proxy_capath : + config->capath)); + if(result && config->proxy_capath) { + warnf("ignoring %s, not supported by libcurl with %s", + config->proxy_capath ? "--proxy-capath" : "--capath", + ssl_backend()); } - else if(result) - return result; } + if(result) + return result; #ifdef CURL_CA_EMBED if(!config->cacert && !config->capath) { @@ -335,47 +330,45 @@ static CURLcode ssl_setopts(struct OperationConfig *config, CURL *curl) #endif if(config->crlfile) - my_setopt_str(curl, CURLOPT_CRLFILE, config->crlfile); + MY_SETOPT_STR(curl, CURLOPT_CRLFILE, config->crlfile); if(config->proxy_crlfile) - my_setopt_str(curl, CURLOPT_PROXY_CRLFILE, config->proxy_crlfile); - else if(config->crlfile) /* CURLOPT_PROXY_CRLFILE default is crlfile */ - my_setopt_str(curl, CURLOPT_PROXY_CRLFILE, config->crlfile); + MY_SETOPT_STR(curl, CURLOPT_PROXY_CRLFILE, config->proxy_crlfile); + else if(config->crlfile) + /* CURLOPT_PROXY_CRLFILE default is crlfile */ + MY_SETOPT_STR(curl, CURLOPT_PROXY_CRLFILE, config->crlfile); if(config->pinnedpubkey) { - result = my_setopt_str(curl, CURLOPT_PINNEDPUBLICKEY, - config->pinnedpubkey); - if(result == CURLE_NOT_BUILT_IN) + MY_SETOPT_STR(curl, CURLOPT_PINNEDPUBLICKEY, config->pinnedpubkey); + if(result) warnf("ignoring %s, not supported by libcurl with %s", "--pinnedpubkey", ssl_backend()); } if(config->proxy_pinnedpubkey) { - result = my_setopt_str(curl, CURLOPT_PROXY_PINNEDPUBLICKEY, - config->proxy_pinnedpubkey); - if(result == CURLE_NOT_BUILT_IN) + MY_SETOPT_STR(curl, CURLOPT_PROXY_PINNEDPUBLICKEY, + config->proxy_pinnedpubkey); + if(result) warnf("ignoring %s, not supported by libcurl with %s", "--proxy-pinnedpubkey", ssl_backend()); } if(config->ssl_ec_curves) - my_setopt_str(curl, CURLOPT_SSL_EC_CURVES, config->ssl_ec_curves); + MY_SETOPT_STR(curl, CURLOPT_SSL_EC_CURVES, config->ssl_ec_curves); if(config->ssl_signature_algorithms) - my_setopt_str(curl, CURLOPT_SSL_SIGNATURE_ALGORITHMS, + MY_SETOPT_STR(curl, CURLOPT_SSL_SIGNATURE_ALGORITHMS, config->ssl_signature_algorithms); if(config->writeout) my_setopt_long(curl, CURLOPT_CERTINFO, 1); - my_setopt_str(curl, CURLOPT_SSLCERT, config->cert); - my_setopt_str(curl, CURLOPT_PROXY_SSLCERT, config->proxy_cert); - my_setopt_str(curl, CURLOPT_SSLCERTTYPE, config->cert_type); - my_setopt_str(curl, CURLOPT_PROXY_SSLCERTTYPE, - config->proxy_cert_type); - my_setopt_str(curl, CURLOPT_SSLKEY, config->key); - my_setopt_str(curl, CURLOPT_PROXY_SSLKEY, config->proxy_key); - my_setopt_str(curl, CURLOPT_SSLKEYTYPE, config->key_type); - my_setopt_str(curl, CURLOPT_PROXY_SSLKEYTYPE, - config->proxy_key_type); + MY_SETOPT_STR(curl, CURLOPT_SSLCERT, config->cert); + MY_SETOPT_STR(curl, CURLOPT_PROXY_SSLCERT, config->proxy_cert); + MY_SETOPT_STR(curl, CURLOPT_SSLCERTTYPE, config->cert_type); + MY_SETOPT_STR(curl, CURLOPT_PROXY_SSLCERTTYPE, config->proxy_cert_type); + MY_SETOPT_STR(curl, CURLOPT_SSLKEY, config->key); + MY_SETOPT_STR(curl, CURLOPT_PROXY_SSLKEY, config->proxy_key); + MY_SETOPT_STR(curl, CURLOPT_SSLKEYTYPE, config->key_type); + MY_SETOPT_STR(curl, CURLOPT_PROXY_SSLKEYTYPE, config->proxy_key_type); /* libcurl default is strict verifyhost -> 1L, verifypeer -> 1L */ if(config->insecure_ok) { @@ -422,8 +415,7 @@ static CURLcode ssl_setopts(struct OperationConfig *config, CURL *curl) { long mask = (config->proxy_ssl_allow_beast ? CURLSSLOPT_ALLOW_BEAST : 0) | - (config->proxy_ssl_auto_client_cert ? - CURLSSLOPT_AUTO_CLIENT_CERT : 0) | + (config->proxy_ssl_auto_client_cert ? CURLSSLOPT_AUTO_CLIENT_CERT : 0) | (config->proxy_native_ca_store ? CURLSSLOPT_NATIVE_CA : 0); if(mask) @@ -431,30 +423,28 @@ static CURLcode ssl_setopts(struct OperationConfig *config, CURL *curl) } if(config->cipher_list) { - result = my_setopt_str(curl, CURLOPT_SSL_CIPHER_LIST, - config->cipher_list); - if(result == CURLE_NOT_BUILT_IN) + MY_SETOPT_STR(curl, CURLOPT_SSL_CIPHER_LIST, config->cipher_list); + if(result) warnf("ignoring %s, not supported by libcurl with %s", "--ciphers", ssl_backend()); } if(config->proxy_cipher_list) { - result = my_setopt_str(curl, CURLOPT_PROXY_SSL_CIPHER_LIST, - config->proxy_cipher_list); - if(result == CURLE_NOT_BUILT_IN) + MY_SETOPT_STR(curl, CURLOPT_PROXY_SSL_CIPHER_LIST, + config->proxy_cipher_list); + if(result) warnf("ignoring %s, not supported by libcurl with %s", "--proxy-ciphers", ssl_backend()); } if(config->cipher13_list) { - result = my_setopt_str(curl, CURLOPT_TLS13_CIPHERS, - config->cipher13_list); - if(result == CURLE_NOT_BUILT_IN) + MY_SETOPT_STR(curl, CURLOPT_TLS13_CIPHERS, config->cipher13_list); + if(result) warnf("ignoring %s, not supported by libcurl with %s", "--tls13-ciphers", ssl_backend()); } if(config->proxy_cipher13_list) { - result = my_setopt_str(curl, CURLOPT_PROXY_TLS13_CIPHERS, - config->proxy_cipher13_list); - if(result == CURLE_NOT_BUILT_IN) + MY_SETOPT_STR(curl, CURLOPT_PROXY_TLS13_CIPHERS, + config->proxy_cipher13_list); + if(result) warnf("ignoring %s, not supported by libcurl with %s", "--proxy-tls13-ciphers", ssl_backend()); } @@ -467,29 +457,22 @@ static CURLcode ssl_setopts(struct OperationConfig *config, CURL *curl) if(feature_ech) { /* only if enabled in libcurl */ if(config->ech) /* only if set (optional) */ - my_setopt_str(curl, CURLOPT_ECH, config->ech); + MY_SETOPT_STR(curl, CURLOPT_ECH, config->ech); if(config->ech_public) /* only if set (optional) */ - my_setopt_str(curl, CURLOPT_ECH, config->ech_public); + MY_SETOPT_STR(curl, CURLOPT_ECH, config->ech_public); if(config->ech_config) /* only if set (optional) */ - my_setopt_str(curl, CURLOPT_ECH, config->ech_config); + MY_SETOPT_STR(curl, CURLOPT_ECH, config->ech_config); } - /* new in curl 7.9.3 */ - if(config->engine) { - result = my_setopt_str(curl, CURLOPT_SSLENGINE, config->engine); - if(result) - return result; - } + if(config->engine) + MY_SETOPT_STR(curl, CURLOPT_SSLENGINE, config->engine); - /* new in curl 7.15.5 */ if(config->ftp_ssl_reqd) my_setopt_enum(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL); - /* new in curl 7.11.0 */ else if(config->ftp_ssl) my_setopt_enum(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY); - /* new in curl 7.16.0 */ else if(config->ftp_ssl_control) my_setopt_enum(curl, CURLOPT_USE_SSL, CURLUSESSL_CONTROL); @@ -500,31 +483,26 @@ static CURLcode ssl_setopts(struct OperationConfig *config, CURL *curl) } /* only called for HTTP transfers */ -static CURLcode http_setopts(struct OperationConfig *config, - CURL *curl) +static CURLcode http_setopts(struct OperationConfig *config, CURL *curl) { + CURLcode result; long postRedir = 0; my_setopt_long(curl, CURLOPT_FOLLOWLOCATION, config->followlocation); - my_setopt_long(curl, CURLOPT_UNRESTRICTED_AUTH, - config->unrestricted_auth); - my_setopt_str(curl, CURLOPT_AWS_SIGV4, config->aws_sigv4); + my_setopt_long(curl, CURLOPT_UNRESTRICTED_AUTH, config->unrestricted_auth); + MY_SETOPT_STR(curl, CURLOPT_AWS_SIGV4, config->aws_sigv4); my_setopt_long(curl, CURLOPT_AUTOREFERER, config->autoreferer); - /* new in libcurl 7.36.0 */ if(config->proxyheaders) { my_setopt_slist(curl, CURLOPT_PROXYHEADER, config->proxyheaders); my_setopt_long(curl, CURLOPT_HEADEROPT, CURLHEADER_SEPARATE); } - /* new in libcurl 7.5 */ my_setopt_long(curl, CURLOPT_MAXREDIRS, config->maxredirs); if(config->httpversion) my_setopt_enum(curl, CURLOPT_HTTP_VERSION, config->httpversion); - /* curl 7.19.1 (the 301 version existed in 7.18.2), - 303 was added in 7.26.0 */ if(config->post301) postRedir |= CURL_REDIR_POST_301; if(config->post302) @@ -533,28 +511,25 @@ static CURLcode http_setopts(struct OperationConfig *config, postRedir |= CURL_REDIR_POST_303; my_setopt_long(curl, CURLOPT_POSTREDIR, postRedir); - /* new in libcurl 7.21.6 */ if(config->encoding) - my_setopt_str(curl, CURLOPT_ACCEPT_ENCODING, ""); + MY_SETOPT_STR(curl, CURLOPT_ACCEPT_ENCODING, ""); - /* new in libcurl 7.21.6 */ if(config->tr_encoding) my_setopt_long(curl, CURLOPT_TRANSFER_ENCODING, 1); - /* new in libcurl 7.64.0 */ + my_setopt_long(curl, CURLOPT_HTTP09_ALLOWED, config->http09_allowed); if(config->altsvc) - my_setopt_str(curl, CURLOPT_ALTSVC, config->altsvc); + MY_SETOPT_STR(curl, CURLOPT_ALTSVC, config->altsvc); if(config->hsts) - my_setopt_str(curl, CURLOPT_HSTS, config->hsts); + MY_SETOPT_STR(curl, CURLOPT_HSTS, config->hsts); - /* new in 7.47.0 */ if(config->expect100timeout_ms > 0) my_setopt_long(curl, CURLOPT_EXPECT_100_TIMEOUT_MS, config->expect100timeout_ms); - return CURLE_OK; + return result; } static CURLcode cookie_setopts(struct OperationConfig *config, CURL *curl) @@ -580,29 +555,28 @@ static CURLcode cookie_setopts(struct OperationConfig *config, CURL *curl) } } - my_setopt_str(curl, CURLOPT_COOKIE, curlx_dyn_ptr(&cookies)); + result = my_setopt_str(curl, CURLOPT_COOKIE, curlx_dyn_ptr(&cookies)); curlx_dyn_free(&cookies); + if(result) + return result; } if(config->cookiefiles) { struct curl_slist *cfl; for(cfl = config->cookiefiles; cfl; cfl = cfl->next) - my_setopt_str(curl, CURLOPT_COOKIEFILE, cfl->data); + MY_SETOPT_STR(curl, CURLOPT_COOKIEFILE, cfl->data); } - /* new in libcurl 7.9 */ if(config->cookiejar) - my_setopt_str(curl, CURLOPT_COOKIEJAR, config->cookiejar); + MY_SETOPT_STR(curl, CURLOPT_COOKIEJAR, config->cookiejar); - /* new in libcurl 7.9.7 */ my_setopt_long(curl, CURLOPT_COOKIESESSION, config->cookiesession); return result; } -static CURLcode tcp_setopts(struct OperationConfig *config, - CURL *curl) +static void tcp_setopts(struct OperationConfig *config, CURL *curl) { if(!config->tcp_nodelay) my_setopt_long(curl, CURLOPT_TCP_NODELAY, 0); @@ -611,7 +585,7 @@ static CURLcode tcp_setopts(struct OperationConfig *config, my_setopt_long(curl, CURLOPT_TCP_FASTOPEN, 1); if(config->mptcp) - my_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, tool_socket_open_mptcp_cb); + my_setopt_ptr(curl, CURLOPT_OPENSOCKETFUNCTION, tool_socket_open_mptcp_cb); /* curl 7.17.1 */ if(!config->nokeepalive) { @@ -625,51 +599,41 @@ static CURLcode tcp_setopts(struct OperationConfig *config, } else my_setopt_long(curl, CURLOPT_TCP_KEEPALIVE, 0); - return CURLE_OK; } static CURLcode ftp_setopts(struct OperationConfig *config, CURL *curl) { - my_setopt_str(curl, CURLOPT_FTPPORT, config->ftpport); + CURLcode result; + MY_SETOPT_STR(curl, CURLOPT_FTPPORT, config->ftpport); - /* new in libcurl 7.9.2: */ if(config->disable_epsv) /* disable it */ my_setopt_long(curl, CURLOPT_FTP_USE_EPSV, 0); - /* new in libcurl 7.10.5 */ if(config->disable_eprt) /* disable it */ my_setopt_long(curl, CURLOPT_FTP_USE_EPRT, 0); - /* new in curl 7.16.1 */ if(config->ftp_ssl_ccc) my_setopt_enum(curl, CURLOPT_FTP_SSL_CCC, config->ftp_ssl_ccc_mode); - my_setopt_str(curl, CURLOPT_FTP_ACCOUNT, config->ftp_account); - - /* curl 7.14.2 */ + MY_SETOPT_STR(curl, CURLOPT_FTP_ACCOUNT, config->ftp_account); my_setopt_long(curl, CURLOPT_FTP_SKIP_PASV_IP, config->ftp_skip_ip); - - /* curl 7.15.1 */ my_setopt_long(curl, CURLOPT_FTP_FILEMETHOD, config->ftp_filemethod); - - /* curl 7.15.5 */ - my_setopt_str(curl, CURLOPT_FTP_ALTERNATIVE_TO_USER, + MY_SETOPT_STR(curl, CURLOPT_FTP_ALTERNATIVE_TO_USER, config->ftp_alternative_to_user); - /* curl 7.20.x */ if(config->ftp_pret) my_setopt_long(curl, CURLOPT_FTP_USE_PRET, 1); - return CURLE_OK; + return result; } static void gen_trace_setopts(struct OperationConfig *config, CURL *curl) { if(global->tracetype != TRACE_NONE) { - my_setopt(curl, CURLOPT_DEBUGFUNCTION, tool_debug_cb); - my_setopt(curl, CURLOPT_DEBUGDATA, config); + my_setopt_ptr(curl, CURLOPT_DEBUGFUNCTION, tool_debug_cb); + my_setopt_ptr(curl, CURLOPT_DEBUGDATA, config); my_setopt_long(curl, CURLOPT_VERBOSE, 1L); } } @@ -681,45 +645,45 @@ static void gen_cb_setopts(struct OperationConfig *config, (void)config; /* when --libcurl is disabled */ /* where to store */ - my_setopt(curl, CURLOPT_WRITEDATA, per); - my_setopt(curl, CURLOPT_INTERLEAVEDATA, per); + my_setopt_ptr(curl, CURLOPT_WRITEDATA, per); + my_setopt_ptr(curl, CURLOPT_INTERLEAVEDATA, per); /* what call to write */ - my_setopt(curl, CURLOPT_WRITEFUNCTION, tool_write_cb); + my_setopt_ptr(curl, CURLOPT_WRITEFUNCTION, tool_write_cb); /* what to read */ - my_setopt(curl, CURLOPT_READDATA, per); - my_setopt(curl, CURLOPT_READFUNCTION, tool_read_cb); + my_setopt_ptr(curl, CURLOPT_READDATA, per); + my_setopt_ptr(curl, CURLOPT_READFUNCTION, tool_read_cb); /* in 7.18.0, the CURLOPT_SEEKFUNCTION/DATA pair is taking over what CURLOPT_IOCTLFUNCTION/DATA pair previously provided for seeking */ - my_setopt(curl, CURLOPT_SEEKDATA, per); - my_setopt(curl, CURLOPT_SEEKFUNCTION, tool_seek_cb); + my_setopt_ptr(curl, CURLOPT_SEEKDATA, per); + my_setopt_ptr(curl, CURLOPT_SEEKFUNCTION, tool_seek_cb); if((global->progressmode == CURL_PROGRESS_BAR) && !global->noprogress && !global->silent) { /* we want the alternative style, then we have to implement it ourselves! */ - my_setopt(curl, CURLOPT_XFERINFOFUNCTION, tool_progress_cb); - my_setopt(curl, CURLOPT_XFERINFODATA, per); + my_setopt_ptr(curl, CURLOPT_XFERINFOFUNCTION, tool_progress_cb); + my_setopt_ptr(curl, CURLOPT_XFERINFODATA, per); } else if(per->uploadfile && !strcmp(per->uploadfile, ".")) { /* when reading from stdin in non-blocking mode, we use the progress function to unpause a busy read */ my_setopt_long(curl, CURLOPT_NOPROGRESS, 0); - my_setopt(curl, CURLOPT_XFERINFOFUNCTION, tool_readbusy_cb); - my_setopt(curl, CURLOPT_XFERINFODATA, per); + my_setopt_ptr(curl, CURLOPT_XFERINFOFUNCTION, tool_readbusy_cb); + my_setopt_ptr(curl, CURLOPT_XFERINFODATA, per); } - my_setopt(curl, CURLOPT_HEADERFUNCTION, tool_header_cb); - my_setopt(curl, CURLOPT_HEADERDATA, per); + my_setopt_ptr(curl, CURLOPT_HEADERFUNCTION, tool_header_cb); + my_setopt_ptr(curl, CURLOPT_HEADERDATA, per); } static CURLcode proxy_setopts(struct OperationConfig *config, CURL *curl) { + CURLcode result; if(config->proxy) { - CURLcode result = my_setopt_str(curl, CURLOPT_PROXY, config->proxy); - + result = my_setopt_str(curl, CURLOPT_PROXY, config->proxy); if(result) { errorf("proxy support is disabled in this libcurl"); config->synthetic_error = TRUE; @@ -727,20 +691,14 @@ static CURLcode proxy_setopts(struct OperationConfig *config, CURL *curl) } } - /* new in libcurl 7.5 */ if(config->proxy) my_setopt_enum(curl, CURLOPT_PROXYTYPE, config->proxyver); - my_setopt_str(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd); - - /* new in libcurl 7.3 */ + MY_SETOPT_STR(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd); my_setopt_long(curl, CURLOPT_HTTPPROXYTUNNEL, config->proxytunnel); - - /* new in libcurl 7.52.0 */ if(config->preproxy) - my_setopt_str(curl, CURLOPT_PRE_PROXY, config->preproxy); + MY_SETOPT_STR(curl, CURLOPT_PRE_PROXY, config->preproxy); - /* new in libcurl 7.10.6 */ if(config->proxyanyauth) my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, CURLAUTH_ANY); else if(config->proxynegotiate) @@ -752,45 +710,42 @@ static CURLcode proxy_setopts(struct OperationConfig *config, CURL *curl) else if(config->proxybasic) my_setopt_bitmask(curl, CURLOPT_PROXYAUTH, CURLAUTH_BASIC); - /* new in libcurl 7.19.4 */ - my_setopt_str(curl, CURLOPT_NOPROXY, config->noproxy); - + MY_SETOPT_STR(curl, CURLOPT_NOPROXY, config->noproxy); my_setopt_long(curl, CURLOPT_SUPPRESS_CONNECT_HEADERS, config->suppress_connect_headers); - /* new in curl 7.43.0 */ if(config->proxy_service_name) - my_setopt_str(curl, CURLOPT_PROXY_SERVICE_NAME, + MY_SETOPT_STR(curl, CURLOPT_PROXY_SERVICE_NAME, config->proxy_service_name); - /* new in 7.60.0 */ if(config->haproxy_protocol) my_setopt_long(curl, CURLOPT_HAPROXYPROTOCOL, 1); - /* new in 8.2.0 */ if(config->haproxy_clientip) - my_setopt_str(curl, CURLOPT_HAPROXY_CLIENT_IP, config->haproxy_clientip); + MY_SETOPT_STR(curl, CURLOPT_HAPROXY_CLIENT_IP, config->haproxy_clientip); - return CURLE_OK; + return result; } -static void tls_srp_setopts(struct OperationConfig *config, CURL *curl) +static CURLcode tls_srp_setopts(struct OperationConfig *config, CURL *curl) { + CURLcode result = CURLE_OK; if(config->tls_username) - my_setopt_str(curl, CURLOPT_TLSAUTH_USERNAME, config->tls_username); + MY_SETOPT_STR(curl, CURLOPT_TLSAUTH_USERNAME, config->tls_username); if(config->tls_password) - my_setopt_str(curl, CURLOPT_TLSAUTH_PASSWORD, config->tls_password); + MY_SETOPT_STR(curl, CURLOPT_TLSAUTH_PASSWORD, config->tls_password); if(config->tls_authtype) - my_setopt_str(curl, CURLOPT_TLSAUTH_TYPE, config->tls_authtype); + MY_SETOPT_STR(curl, CURLOPT_TLSAUTH_TYPE, config->tls_authtype); if(config->proxy_tls_username) - my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_USERNAME, + MY_SETOPT_STR(curl, CURLOPT_PROXY_TLSAUTH_USERNAME, config->proxy_tls_username); if(config->proxy_tls_password) - my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_PASSWORD, + MY_SETOPT_STR(curl, CURLOPT_PROXY_TLSAUTH_PASSWORD, config->proxy_tls_password); if(config->proxy_tls_authtype) - my_setopt_str(curl, CURLOPT_PROXY_TLSAUTH_TYPE, + MY_SETOPT_STR(curl, CURLOPT_PROXY_TLSAUTH_TYPE, config->proxy_tls_authtype); + return result; } CURLcode config2setopts(struct OperationConfig *config, @@ -838,21 +793,20 @@ CURLcode config2setopts(struct OperationConfig *config, my_setopt_long(curl, CURLOPT_BUFFERSIZE, BUFFER_SIZE); } - my_setopt_str(curl, CURLOPT_URL, per->url); + MY_SETOPT_STR(curl, CURLOPT_URL, per->url); my_setopt_long(curl, CURLOPT_NOPROGRESS, global->noprogress || global->silent); /* call after the line above. It may override CURLOPT_NOPROGRESS */ gen_cb_setopts(config, per, curl); my_setopt_long(curl, CURLOPT_NOBODY, config->no_body); - my_setopt_str(curl, CURLOPT_XOAUTH2_BEARER, config->oauth_bearer); - + MY_SETOPT_STR(curl, CURLOPT_XOAUTH2_BEARER, config->oauth_bearer); result = proxy_setopts(config, curl); - if(result) + if(setopt_bad(result) || config->synthetic_error) return result; my_setopt_long(curl, CURLOPT_FAILONERROR, config->fail == FAIL_WO_BODY); - my_setopt_str(curl, CURLOPT_REQUEST_TARGET, config->request_target); + MY_SETOPT_STR(curl, CURLOPT_REQUEST_TARGET, config->request_target); my_setopt_long(curl, CURLOPT_UPLOAD, !!per->uploadfile); my_setopt_long(curl, CURLOPT_DIRLISTONLY, config->dirlistonly); my_setopt_long(curl, CURLOPT_APPEND, config->ftp_append); @@ -864,12 +818,12 @@ CURLcode config2setopts(struct OperationConfig *config, else my_setopt_enum(curl, CURLOPT_NETRC, CURL_NETRC_IGNORED); - my_setopt_str(curl, CURLOPT_NETRC_FILE, config->netrc_file); + MY_SETOPT_STR(curl, CURLOPT_NETRC_FILE, config->netrc_file); my_setopt_long(curl, CURLOPT_TRANSFERTEXT, config->use_ascii); - my_setopt_str(curl, CURLOPT_LOGIN_OPTIONS, config->login_options); - my_setopt_str(curl, CURLOPT_USERPWD, config->userpwd); - my_setopt_str(curl, CURLOPT_RANGE, config->range); - my_setopt(curl, CURLOPT_ERRORBUFFER, per->errorbuffer); + MY_SETOPT_STR(curl, CURLOPT_LOGIN_OPTIONS, config->login_options); + MY_SETOPT_STR(curl, CURLOPT_USERPWD, config->userpwd); + MY_SETOPT_STR(curl, CURLOPT_RANGE, config->range); + my_setopt_ptr(curl, CURLOPT_ERRORBUFFER, per->errorbuffer); my_setopt_long(curl, CURLOPT_TIMEOUT_MS, config->timeout_ms); switch(config->httpreq) { @@ -879,7 +833,7 @@ CURLcode config2setopts(struct OperationConfig *config, result = CURLE_FAILED_INIT; } else { - my_setopt_str(curl, CURLOPT_POSTFIELDS, + MY_SETOPT_STR(curl, CURLOPT_POSTFIELDS, curlx_dyn_ptr(&config->postdata)); my_setopt_offt(curl, CURLOPT_POSTFIELDSIZE_LARGE, curlx_dyn_len(&config->postdata)); @@ -914,8 +868,9 @@ CURLcode config2setopts(struct OperationConfig *config, my_setopt_slist(curl, CURLOPT_HTTPHEADER, config->headers); if(proto_http || proto_rtsp) { - my_setopt_str(curl, CURLOPT_REFERER, config->referer); - my_setopt_str(curl, CURLOPT_USERAGENT, config->useragent); + MY_SETOPT_STR(curl, CURLOPT_REFERER, config->referer); + MY_SETOPT_STR(curl, CURLOPT_USERAGENT, config->useragent ? + config->useragent : CURL_NAME "/" CURL_VERSION); } if(use_proto == proto_http || use_proto == proto_https) { @@ -942,28 +897,26 @@ CURLcode config2setopts(struct OperationConfig *config, else my_setopt_offt(curl, CURLOPT_RESUME_FROM_LARGE, 0); - my_setopt_str(curl, CURLOPT_KEYPASSWD, config->key_passwd); - my_setopt_str(curl, CURLOPT_PROXY_KEYPASSWD, config->proxy_key_passwd); + MY_SETOPT_STR(curl, CURLOPT_KEYPASSWD, config->key_passwd); + MY_SETOPT_STR(curl, CURLOPT_PROXY_KEYPASSWD, config->proxy_key_passwd); if(use_proto == proto_scp || use_proto == proto_sftp) { result = ssh_setopts(config, curl); - if(result) + if(setopt_bad(result)) return result; } - if(feature_ssl) { result = ssl_setopts(config, curl); - if(result) + if(setopt_bad(result)) return result; } if(config->path_as_is) my_setopt_long(curl, CURLOPT_PATH_AS_IS, 1); - if(config->no_body || config->remote_time) { + if(config->no_body || config->remote_time) /* no body or use remote time */ my_setopt_long(curl, CURLOPT_FILETIME, 1); - } my_setopt_long(curl, CURLOPT_CRLF, config->crlf); my_setopt_slist(curl, CURLOPT_QUOTE, config->quote); @@ -972,29 +925,28 @@ CURLcode config2setopts(struct OperationConfig *config, my_setopt_enum(curl, CURLOPT_TIMECONDITION, config->timecond); my_setopt_offt(curl, CURLOPT_TIMEVALUE_LARGE, config->condtime); - my_setopt_str(curl, CURLOPT_CUSTOMREQUEST, config->customrequest); + MY_SETOPT_STR(curl, CURLOPT_CUSTOMREQUEST, config->customrequest); customrequest_helper(config->httpreq, config->customrequest); - my_setopt(curl, CURLOPT_STDERR, tool_stderr); - my_setopt_str(curl, CURLOPT_INTERFACE, config->iface); + my_setopt_ptr(curl, CURLOPT_STDERR, tool_stderr); + MY_SETOPT_STR(curl, CURLOPT_INTERFACE, config->iface); progressbarinit(&per->progressbar, config); - my_setopt_str(curl, CURLOPT_DNS_SERVERS, config->dns_servers); - my_setopt_str(curl, CURLOPT_DNS_INTERFACE, config->dns_interface); - my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP4, config->dns_ipv4_addr); - my_setopt_str(curl, CURLOPT_DNS_LOCAL_IP6, config->dns_ipv6_addr); + MY_SETOPT_STR(curl, CURLOPT_DNS_SERVERS, config->dns_servers); + MY_SETOPT_STR(curl, CURLOPT_DNS_INTERFACE, config->dns_interface); + MY_SETOPT_STR(curl, CURLOPT_DNS_LOCAL_IP4, config->dns_ipv4_addr); + MY_SETOPT_STR(curl, CURLOPT_DNS_LOCAL_IP6, config->dns_ipv6_addr); my_setopt_slist(curl, CURLOPT_TELNETOPTIONS, config->telnet_options); my_setopt_long(curl, CURLOPT_CONNECTTIMEOUT_MS, config->connecttimeout_ms); - my_setopt_str(curl, CURLOPT_DOH_URL, config->doh_url); + MY_SETOPT_STR(curl, CURLOPT_DOH_URL, config->doh_url); my_setopt_long(curl, CURLOPT_FTP_CREATE_MISSING_DIRS, (config->ftp_create_dirs ? CURLFTP_CREATE_DIR_RETRY : CURLFTP_CREATE_DIR_NONE)); - my_setopt_offt(curl, CURLOPT_MAXFILESIZE_LARGE, - config->max_filesize); + my_setopt_offt(curl, CURLOPT_MAXFILESIZE_LARGE, config->max_filesize); my_setopt_long(curl, CURLOPT_IPRESOLVE, config->ip_version); if(config->socks5_gssapi_nec) my_setopt_long(curl, CURLOPT_SOCKS5_GSSAPI_NEC, 1); if(config->socks5_auth) my_setopt_bitmask(curl, CURLOPT_SOCKS5_AUTH, config->socks5_auth); - my_setopt_str(curl, CURLOPT_SERVICE_NAME, config->service_name); + MY_SETOPT_STR(curl, CURLOPT_SERVICE_NAME, config->service_name); my_setopt_long(curl, CURLOPT_IGNORE_CONTENT_LENGTH, config->ignorecl); if(config->localport) { @@ -1007,14 +959,12 @@ CURLcode config2setopts(struct OperationConfig *config, my_setopt_long(curl, CURLOPT_HTTP_TRANSFER_DECODING, 0); } - result = tcp_setopts(config, curl); - if(result) - return result; + tcp_setopts(config, curl); if(config->tftp_blksize && proto_tftp) my_setopt_long(curl, CURLOPT_TFTP_BLKSIZE, config->tftp_blksize); - my_setopt_str(curl, CURLOPT_MAIL_FROM, config->mail_from); + MY_SETOPT_STR(curl, CURLOPT_MAIL_FROM, config->mail_from); my_setopt_slist(curl, CURLOPT_MAIL_RCPT, config->mail_rcpt); my_setopt_long(curl, CURLOPT_MAIL_RCPT_ALLOWFAILS, config->mail_rcpt_allowfails); @@ -1022,35 +972,36 @@ CURLcode config2setopts(struct OperationConfig *config, my_setopt_long(curl, CURLOPT_NEW_FILE_PERMS, config->create_file_mode); if(config->proto_present) - my_setopt_str(curl, CURLOPT_PROTOCOLS_STR, config->proto_str); + MY_SETOPT_STR(curl, CURLOPT_PROTOCOLS_STR, config->proto_str); if(config->proto_redir_present) - my_setopt_str(curl, CURLOPT_REDIR_PROTOCOLS_STR, config->proto_redir_str); + MY_SETOPT_STR(curl, CURLOPT_REDIR_PROTOCOLS_STR, config->proto_redir_str); my_setopt_slist(curl, CURLOPT_RESOLVE, config->resolve); my_setopt_slist(curl, CURLOPT_CONNECT_TO, config->connect_to); - if(feature_tls_srp) - tls_srp_setopts(config, curl); + if(feature_tls_srp) { + result = tls_srp_setopts(config, curl); + if(setopt_bad(result)) + return result; + } if(config->gssapi_delegation) my_setopt_long(curl, CURLOPT_GSSAPI_DELEGATION, config->gssapi_delegation); - my_setopt_str(curl, CURLOPT_MAIL_AUTH, config->mail_auth); - my_setopt_str(curl, CURLOPT_SASL_AUTHZID, config->sasl_authzid); + MY_SETOPT_STR(curl, CURLOPT_MAIL_AUTH, config->mail_auth); + MY_SETOPT_STR(curl, CURLOPT_SASL_AUTHZID, config->sasl_authzid); my_setopt_long(curl, CURLOPT_SASL_IR, config->sasl_ir); if(config->unix_socket_path) { - if(config->abstract_unix_socket) { - my_setopt_str(curl, CURLOPT_ABSTRACT_UNIX_SOCKET, + if(config->abstract_unix_socket) + MY_SETOPT_STR(curl, CURLOPT_ABSTRACT_UNIX_SOCKET, config->unix_socket_path); - } - else { - my_setopt_str(curl, CURLOPT_UNIX_SOCKET_PATH, + else + MY_SETOPT_STR(curl, CURLOPT_UNIX_SOCKET_PATH, config->unix_socket_path); - } } - my_setopt_str(curl, CURLOPT_DEFAULT_PROTOCOL, config->proto_default); + MY_SETOPT_STR(curl, CURLOPT_DEFAULT_PROTOCOL, config->proto_default); my_setopt_long(curl, CURLOPT_TFTP_NO_OPTIONS, config->tftp_no_options && proto_tftp); @@ -1063,8 +1014,8 @@ CURLcode config2setopts(struct OperationConfig *config, if(config->ip_tos > 0 || config->vlan_priority > 0) { #if defined(IP_TOS) || defined(IPV6_TCLASS) || defined(SO_PRIORITY) - my_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback); - my_setopt(curl, CURLOPT_SOCKOPTDATA, config); + my_setopt_ptr(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback); + my_setopt_ptr(curl, CURLOPT_SOCKOPTDATA, config); #else if(config->ip_tos > 0) { errorf("Type of service is not supported in this build."); diff --git a/src/curlinfo.c b/src/curlinfo.c index da75a45876cf..8716b72437c7 100644 --- a/src/curlinfo.c +++ b/src/curlinfo.c @@ -39,7 +39,7 @@ #include "fake_addrinfo.h" /* for USE_FAKE_GETADDRINFO */ #include -static const char *disabled[]={ +static const char *disabled[] = { "bindlocal: " #ifdef CURL_DISABLE_BINDLOCAL "OFF" @@ -235,6 +235,13 @@ static const char *disabled[]={ "ON" #else "OFF" +#endif + , + "ssl-sessions: " +#ifdef USE_SSLS_EXPORT + "ON" +#else + "OFF" #endif }; @@ -246,8 +253,7 @@ int main(int argc, char **argv) (void)argv; for(i = 0; i < CURL_ARRAYSIZE(disabled); i++) - /* !checksrc! disable BANNEDFUNC 1 */ - printf("%s\n", disabled[i]); + puts(disabled[i]); return 0; } diff --git a/src/mkhelp.pl b/src/mkhelp.pl index d1a040c0cc63..b3a6c5abdce7 100755 --- a/src/mkhelp.pl +++ b/src/mkhelp.pl @@ -78,7 +78,6 @@ print < -#include /* keep this as LAST include */ static const unsigned char hugehelpgz[] = { /* This mumbo-jumbo is the huge help text compressed with gzip. Thanks to this operation, the size of this data shrank from $gzip @@ -105,13 +104,13 @@ static voidpf zalloc_func(voidpf opaque, unsigned int items, unsigned int size) { (void)opaque; - /* not a typo, keep it calloc() */ - return (voidpf) calloc(items, size); + /* not a typo, keep it curlx_calloc() */ + return (voidpf)curlx_calloc(items, size); } static void zfree_func(voidpf opaque, voidpf ptr) { (void)opaque; - free(ptr); + curlx_free(ptr); } #define HEADERLEN 10 @@ -136,7 +135,7 @@ if(inflateInit2(&z, -MAX_WBITS) != Z_OK) return; - buf = malloc(BUF_SIZE); + buf = curlx_malloc(BUF_SIZE); if(buf) { while(1) { z.avail_out = BUF_SIZE; @@ -150,7 +149,7 @@ else break; /* error */ } - free(buf); + curlx_free(buf); } inflateEnd(&z); } @@ -176,7 +175,7 @@ if(inflateInit2(&z, -MAX_WBITS) != Z_OK) return; - buf = malloc(BUF_SIZE); + buf = curlx_malloc(BUF_SIZE); if(buf) { while(1) { z.avail_out = BUF_SIZE; @@ -192,7 +191,7 @@ else break; /* error */ } - free(buf); + curlx_free(buf); } inflateEnd(&z); } diff --git a/src/slist_wc.c b/src/slist_wc.c index 7f1e8f19be8d..8a3ff254ccbc 100644 --- a/src/slist_wc.c +++ b/src/slist_wc.c @@ -28,15 +28,11 @@ #include "slist_wc.h" -/* The last #include files should be: */ -#include "memdebug.h" - /* * slist_wc_append() appends a string to the linked list. This function can be * used as an initialization function as well as an append function. */ -struct slist_wc *slist_wc_append(struct slist_wc *list, - const char *data) +struct slist_wc *slist_wc_append(struct slist_wc *list, const char *data) { struct curl_slist *new_item = curl_slist_append(NULL, data); @@ -44,7 +40,7 @@ struct slist_wc *slist_wc_append(struct slist_wc *list, return NULL; if(!list) { - list = malloc(sizeof(struct slist_wc)); + list = curlx_malloc(sizeof(struct slist_wc)); if(!list) { curl_slist_free_all(new_item); @@ -68,7 +64,7 @@ void slist_wc_free_all(struct slist_wc *list) return; curl_slist_free_all(list->first); - free(list); + curlx_free(list); } #endif /* CURL_DISABLE_LIBCURL_OPTION */ diff --git a/src/terminal.c b/src/terminal.c index 014e2df8c00b..fe945cfa9c7b 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -28,7 +28,6 @@ #endif #include "terminal.h" -#include "memdebug.h" /* keep this as LAST include */ #ifdef HAVE_TERMIOS_H # include @@ -64,7 +63,7 @@ unsigned int get_terminal_columns(void) struct winsize ts; if(!ioctl(STDIN_FILENO, TIOCGWINSZ, &ts)) cols = (int)ts.ws_col; -#elif defined(_WIN32) && !defined(CURL_WINDOWS_UWP) && !defined(UNDER_CE) +#elif defined(_WIN32) && !defined(CURL_WINDOWS_UWP) { HANDLE stderr_hnd = GetStdHandle(STD_ERROR_HANDLE); CONSOLE_SCREEN_BUFFER_INFO console_info; @@ -75,8 +74,7 @@ unsigned int get_terminal_columns(void) * Do not use +1 to get the true screen-width since writing a * character at the right edge will cause a line wrap. */ - cols = (int) - (console_info.srWindow.Right - console_info.srWindow.Left); + cols = (int)(console_info.srWindow.Right - console_info.srWindow.Left); } } #endif /* TIOCGSIZE */ diff --git a/src/tool_bname.c b/src/tool_bname.c index 4ba1a3b8eeac..50d77abb9644 100644 --- a/src/tool_bname.c +++ b/src/tool_bname.c @@ -25,8 +25,6 @@ #include "tool_bname.h" -#include "memdebug.h" /* keep this as LAST include */ - #ifndef HAVE_BASENAME char *tool_basename(char *path) diff --git a/src/tool_bname.h b/src/tool_bname.h index d091c2231a8d..4047c5cc78c8 100644 --- a/src/tool_bname.h +++ b/src/tool_bname.h @@ -29,7 +29,7 @@ char *tool_basename(char *path); -#define basename(x) tool_basename((x)) +#define basename(x) tool_basename(x) #endif /* HAVE_BASENAME */ diff --git a/src/tool_cb_dbg.c b/src/tool_cb_dbg.c index 043daef26dd0..6a566c30b097 100644 --- a/src/tool_cb_dbg.c +++ b/src/tool_cb_dbg.c @@ -27,8 +27,7 @@ #include "tool_msgs.h" #include "tool_cb_dbg.h" #include "tool_util.h" - -#include "memdebug.h" /* keep this as LAST include */ +#include "toolx/tool_time.h" static void dump(const char *timebuf, const char *idsbuf, const char *text, FILE *stream, const unsigned char *ptr, size_t size, @@ -36,7 +35,6 @@ static void dump(const char *timebuf, const char *idsbuf, const char *text, /* * Return the formatted HH:MM:SS for the tv_sec given. - * NOT thread safe. */ static const char *hms_for_sec(time_t tv_sec) { @@ -44,10 +42,12 @@ static const char *hms_for_sec(time_t tv_sec) static char hms_buf[12]; if(tv_sec != cached_tv_sec) { - /* !checksrc! disable BANNEDFUNC 1 */ - struct tm *now = localtime(&tv_sec); /* not thread safe either */ + struct tm now; + CURLcode result = toolx_localtime(tv_sec, &now); + if(result) + memset(&now, 0, sizeof(now)); curl_msnprintf(hms_buf, sizeof(hms_buf), "%02d:%02d:%02d", - now->tm_hour, now->tm_min, now->tm_sec); + now.tm_hour, now.tm_min, now.tm_sec); cached_tv_sec = tv_sec; } return hms_buf; @@ -105,7 +105,7 @@ int tool_debug_cb(CURL *handle, curl_infotype type, if(handle && global->traceids && !curl_easy_getinfo(handle, CURLINFO_XFER_ID, &xfer_id) && xfer_id >= 0) { if(!curl_easy_getinfo(handle, CURLINFO_CONN_ID, &conn_id) && - conn_id >= 0) { + conn_id >= 0) { curl_msnprintf(idsbuf, sizeof(idsbuf), TRC_IDS_FORMAT_IDS_2, xfer_id, conn_id); } @@ -226,7 +226,7 @@ int tool_debug_cb(CURL *handle, curl_infotype type, break; } - dump(timebuf, idsbuf, text, output, (unsigned char *) data, size, + dump(timebuf, idsbuf, text, output, (unsigned char *)data, size, global->tracetype, type); return 0; } diff --git a/src/tool_cb_hdr.c b/src/tool_cb_hdr.c index 2ea88017051e..8027ea542171 100644 --- a/src/tool_cb_hdr.c +++ b/src/tool_cb_hdr.c @@ -36,22 +36,20 @@ #include "tool_libinfo.h" #include "tool_strdup.h" -#include "memdebug.h" /* keep this as LAST include */ - static char *parse_filename(const char *ptr, size_t len); #ifdef _WIN32 -#define BOLD "\x1b[1m" +#define BOLD "\x1b[1m" #define BOLDOFF "\x1b[22m" #else -#define BOLD "\x1b[1m" +#define BOLD "\x1b[1m" /* Switch off bold by setting "all attributes off" since the explicit bold-off code (21) is not supported everywhere - like in the mac Terminal. */ #define BOLDOFF "\x1b[0m" /* OSC 8 hyperlink escape sequence */ -#define LINK "\x1b]8;;" -#define LINKST "\x1b\\" +#define LINK "\x1b]8;;" +#define LINKST "\x1b\\" #define LINKOFF LINK LINKST #endif @@ -78,7 +76,6 @@ int tool_write_headers(struct HdrCbData *hdrcbdata, FILE *stream) return rc; } - /* ** callback for CURLOPT_HEADERFUNCTION * @@ -133,7 +130,7 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata) long response = 0; curl_easy_getinfo(per->curl, CURLINFO_RESPONSE_CODE, &response); - if((response/100 != 2) && (response/100 != 3)) + if((response / 100 != 2) && (response / 100 != 3)) /* only care about etag and content-disposition headers in 2xx and 3xx responses */ ; @@ -156,7 +153,7 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata) /* * Truncate the etag save stream, it can have an existing etag value. */ -#if defined(HAVE_FTRUNCATE) && !defined(__MINGW32CE__) +#ifdef HAVE_FTRUNCATE if(ftruncate(fileno(etag_save->stream), 0)) { return CURL_WRITEFUNC_ERROR; } @@ -212,14 +209,14 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata) if(filename) { if(outs->stream) { /* indication of problem, get out! */ - free(filename); + curlx_free(filename); return CURL_WRITEFUNC_ERROR; } if(per->config->output_dir) { outs->filename = curl_maprintf("%s/%s", per->config->output_dir, filename); - free(filename); + curlx_free(filename); if(!outs->filename) return CURL_WRITEFUNC_ERROR; } @@ -252,7 +249,7 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata) if(clone) { struct curl_slist *old = hdrcbdata->headlist; hdrcbdata->headlist = curl_slist_append(old, clone); - free(clone); + curlx_free(clone); if(!hdrcbdata->headlist) { curl_slist_free_all(old); return CURL_WRITEFUNC_ERROR; @@ -301,7 +298,7 @@ size_t tool_header_cb(char *ptr, size_t size, size_t nmemb, void *userdata) #else if(curl_strnequal("Location", ptr, namelen)) { write_linked_location(per->curl, &value[1], cb - namelen - 1, - outs->stream); + outs->stream); } else fwrite(&value[1], cb - namelen - 1, 1, outs->stream); @@ -322,7 +319,7 @@ static char *parse_filename(const char *ptr, size_t len) char *copy; char *p; char *q; - char stop = '\0'; + char stop = '\0'; copy = memdup0(ptr, len); if(!copy) @@ -428,7 +425,7 @@ static void write_linked_location(CURL *curl, const char *location, } /* Strip the trailing end-of-line characters, normally "\r\n" */ - while(llen && (loc[llen-1] == '\n' || loc[llen-1] == '\r')) + while(llen && (loc[llen - 1] == '\n' || loc[llen - 1] == '\r')) --llen; /* CURLU makes it easy to handle the relative URL case */ @@ -479,7 +476,7 @@ static void write_linked_location(CURL *curl, const char *location, curl_free(finalurl); curl_free(scheme); curl_url_cleanup(u); - free(copyloc); + curlx_free(copyloc); } } #endif diff --git a/src/tool_cb_prg.c b/src/tool_cb_prg.c index dd460a4bf6ed..8d9302f2e188 100644 --- a/src/tool_cb_prg.c +++ b/src/tool_cb_prg.c @@ -29,8 +29,6 @@ #include "tool_operate.h" #include "terminal.h" -#include "memdebug.h" /* keep this as LAST include */ - #define MAX_BARLENGTH 400 #define MIN_BARLENGTH 20 @@ -56,14 +54,15 @@ static const int sinus[] = { 500046, 484341, 468651, 452993, 437381, 421830, 406357, 390976, 375703, 360552, 345539, 330679, 315985, 301474, 287158, 273052, 259170, 245525, 232132, 219003, 206152, 193590, 181331, 169386, 157768, 146487, 135555, - 124983, 114781, 104959, 95526, 86493, 77868, 69660, 61876, 54525, 47613, - 41147, 35135, 29581, 24491, 19871, 15724, 12056, 8868, 6166, 3951, 2225, - 990, 248, 0, 244, 982, 2212, 3933, 6144, 8842, 12025, 15690, 19832, 24448, - 29534, 35084, 41092, 47554, 54462, 61809, 69589, 77794, 86415, 95445, - 104873, 114692, 124891, 135460, 146389, 157667, 169282, 181224, 193480, - 206039, 218888, 232015, 245406, 259048, 272928, 287032, 301346, 315856, - 330548, 345407, 360419, 375568, 390841, 406221, 421693, 437243, 452854, - 468513, 484202, 499907 + 124983, 114781, 104959, 95526, 86493, 77868, 69660, 61876, 54525, + 47613, 41147, 35135, 29581, 24491, 19871, 15724, 12056, 8868, + 6166, 3951, 2225, 990, 248, 0, 244, 982, 2212, + 3933, 6144, 8842, 12025, 15690, 19832, 24448, 29534, 35084, + 41092, 47554, 54462, 61809, 69589, 77794, 86415, 95445, 104873, + 114692, 124891, 135460, 146389, 157667, 169282, 181224, 193480, 206039, + 218888, 232015, 245406, 259048, 272928, 287032, 301346, 315856, 330548, + 345407, 360419, 375568, 390841, 406221, 421693, 437243, 452854, 468513, + 484202, 499907 }; static void fly(struct ProgressData *bar, bool moved) @@ -80,13 +79,13 @@ static void fly(struct ProgressData *bar, bool moved) memcpy(&buf[bar->bar + 1], "-=O=-", 5); - pos = sinus[bar->tick%200] / (1000000 / check) + 1; + pos = sinus[bar->tick % 200] / (1000000 / check) + 1; buf[pos] = '#'; - pos = sinus[(bar->tick + 5)%200] / (1000000 / check) + 1; + pos = sinus[(bar->tick + 5) % 200] / (1000000 / check) + 1; buf[pos] = '#'; - pos = sinus[(bar->tick + 10)%200] / (1000000 / check) + 1; + pos = sinus[(bar->tick + 10) % 200] / (1000000 / check) + 1; buf[pos] = '#'; - pos = sinus[(bar->tick + 15)%200] / (1000000 / check) + 1; + pos = sinus[(bar->tick + 15) % 200] / (1000000 / check) + 1; buf[pos] = '#'; fputs(buf, bar->out); @@ -171,13 +170,13 @@ int tool_progress_cb(void *clientp, if(bar->prev == point) /* progress did not change since last invoke */ return 0; - else if((curlx_timediff(now, bar->prevtime) < 100L) && point < total) + else if((curlx_timediff_ms(now, bar->prevtime) < 100L) && point < total) /* limit progress-bar updating to 10 Hz except when we are at 100% */ return 0; } else { /* total is unknown */ - if(curlx_timediff(now, bar->prevtime) < 100L) + if(curlx_timediff_ms(now, bar->prevtime) < 100L) /* limit progress-bar updating to 10 Hz */ return 0; update_width(bar); @@ -203,7 +202,7 @@ int tool_progress_cb(void *clientp, frac = (double)point / (double)total; percent = frac * 100.0; barwidth = bar->width - 7; - num = (size_t) (((double)barwidth) * frac); + num = (size_t)(((double)barwidth) * frac); if(num > MAX_BARLENGTH) num = MAX_BARLENGTH; memset(line, '#', num); @@ -230,8 +229,7 @@ int tool_progress_cb(void *clientp, return 0; } -void progressbarinit(struct ProgressData *bar, - struct OperationConfig *config) +void progressbarinit(struct ProgressData *bar, struct OperationConfig *config) { memset(bar, 0, sizeof(struct ProgressData)); diff --git a/src/tool_cb_prg.h b/src/tool_cb_prg.h index 1f005dbfc4e9..9c2dda2d7e35 100644 --- a/src/tool_cb_prg.h +++ b/src/tool_cb_prg.h @@ -29,12 +29,12 @@ #define CURL_PROGRESS_BAR 1 struct ProgressData { - int calls; - curl_off_t prev; + int calls; + curl_off_t prev; struct curltime prevtime; - int width; - FILE *out; /* where to write everything to */ - curl_off_t initial_size; + int width; + FILE *out; /* where to write everything to */ + curl_off_t initial_size; unsigned int tick; int bar; int barmove; @@ -42,8 +42,7 @@ struct ProgressData { struct OperationConfig; -void progressbarinit(struct ProgressData *bar, - struct OperationConfig *config); +void progressbarinit(struct ProgressData *bar, struct OperationConfig *config); /* ** callback for CURLOPT_PROGRESSFUNCTION diff --git a/src/tool_cb_rea.c b/src/tool_cb_rea.c index b7bd9a722732..1de2277cd084 100644 --- a/src/tool_cb_rea.c +++ b/src/tool_cb_rea.c @@ -26,6 +26,11 @@ #ifdef HAVE_SYS_SELECT_H #include #endif +#ifdef HAVE_POLL_H +#include +#elif defined(HAVE_SYS_POLL_H) +#include +#endif #include "tool_cfgable.h" #include "tool_cb_rea.h" @@ -33,7 +38,48 @@ #include "tool_util.h" #include "tool_msgs.h" -#include "memdebug.h" /* keep this as LAST include */ +#ifndef _WIN32 +/* Wait up to a number of milliseconds for socket activity. This function + waits on read activity on a file descriptor that is not a socket which + makes it not work with select() or poll() on Windows. */ +static bool waitfd(int waitms, int fd) +{ +#ifdef HAVE_POLL + struct pollfd set; + + set.fd = fd; + set.events = POLLIN; + set.revents = 0; + if(poll(&set, 1, (int)waitms)) + return TRUE; /* timeout */ + return FALSE; +#else + fd_set bits; + struct timeval timeout; + + if(fd >= FD_SETSIZE) + /* cannot wait! */ + return FALSE; + + /* wait this long at the most */ + timeout.tv_sec = waitms / 1000; + timeout.tv_usec = (int)((waitms % 1000) * 1000); + + FD_ZERO(&bits); +#ifdef __DJGPP__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warith-conversion" +#endif + FD_SET(fd, &bits); +#ifdef __DJGPP__ +#pragma GCC diagnostic pop +#endif + if(!select(fd + 1, &bits, NULL, NULL, &timeout)) + return TRUE; /* timeout */ + return FALSE; +#endif +} +#endif /* ** callback for CURLOPT_READFUNCTION @@ -53,34 +99,17 @@ size_t tool_read_cb(char *buffer, size_t sz, size_t nmemb, void *userdata) if(config->timeout_ms) { struct curltime now = curlx_now(); - long msdelta = (long)curlx_timediff(now, per->start); + long msdelta = (long)curlx_timediff_ms(now, per->start); if(msdelta > config->timeout_ms) /* timeout */ return 0; #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 { - fd_set bits; - struct timeval timeout; - long wait = config->timeout_ms - msdelta; - - /* wait this long at the most */ - timeout.tv_sec = wait/1000; - timeout.tv_usec = (int)((wait%1000)*1000); - - FD_ZERO(&bits); -#ifdef __DJGPP__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Warith-conversion" -#endif - FD_SET(per->infd, &bits); -#ifdef __DJGPP__ -#pragma GCC diagnostic pop -#endif - if(!select(per->infd + 1, &bits, NULL, NULL, &timeout)) - return 0; /* timeout */ + long w = config->timeout_ms - msdelta; + if(w > INT_MAX) + w = INT_MAX; + waitfd((int)w, per->infd); } #endif } @@ -91,11 +120,11 @@ size_t tool_read_cb(char *buffer, size_t sz, size_t nmemb, void *userdata) On Linux per->infd should be stdin (0) and the block below should not execute */ if(per->uploadfile && !strcmp(per->uploadfile, ".") && per->infd > 0) { -#if defined(_WIN32) && !defined(CURL_WINDOWS_UWP) && !defined(UNDER_CE) +#if defined(_WIN32) && !defined(CURL_WINDOWS_UWP) rc = CURL_RECV(per->infd, buffer, curlx_uztosi(sz * nmemb), 0); if(rc < 0) { if(SOCKERRNO == SOCKEWOULDBLOCK) { - CURL_SETERRNO(0); + errno = 0; config->readbusy = TRUE; return CURL_READFUNC_PAUSE; } @@ -108,10 +137,10 @@ size_t tool_read_cb(char *buffer, size_t sz, size_t nmemb, void *userdata) #endif } else { - rc = read(per->infd, buffer, sz*nmemb); + rc = read(per->infd, buffer, sz * nmemb); if(rc < 0) { if(errno == EAGAIN) { - CURL_SETERRNO(0); + errno = 0; config->readbusy = TRUE; return CURL_READFUNC_PAUSE; } @@ -154,22 +183,7 @@ int tool_readbusy_cb(void *clientp, if(config->readbusy) { if(ulprev == ulnow) { #ifndef _WIN32 - fd_set bits; - struct timeval timeout; - /* wait this long at the most */ - timeout.tv_sec = 0; - timeout.tv_usec = 1000; - - FD_ZERO(&bits); -#ifdef __DJGPP__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Warith-conversion" -#endif - FD_SET(per->infd, &bits); -#ifdef __DJGPP__ -#pragma GCC diagnostic pop -#endif - select(per->infd + 1, &bits, NULL, NULL, &timeout); + waitfd(1, per->infd); #else /* sleep */ curlx_wait_ms(1); diff --git a/src/tool_cb_see.c b/src/tool_cb_see.c index 68899c582950..112faf0dc24a 100644 --- a/src/tool_cb_see.c +++ b/src/tool_cb_see.c @@ -27,8 +27,6 @@ #include "tool_operate.h" #include "tool_cb_see.h" -#include "memdebug.h" /* keep this as LAST include */ - /* ** callback for CURLOPT_SEEKFUNCTION ** @@ -40,14 +38,14 @@ int tool_seek_cb(void *userdata, curl_off_t offset, int whence) { struct per_transfer *per = userdata; -#if (SIZEOF_CURL_OFF_T > SIZEOF_OFF_T) && !defined(USE_WIN32_LARGE_FILES) +#if (SIZEOF_CURL_OFF_T > SIZEOF_OFF_T) && !defined(_WIN32) /* OUR_MAX_SEEK_L has 'long' data type, OUR_MAX_SEEK_O has 'curl_off_t, both represent the same value. Maximum offset used here when we lseek using a 'long' data type offset */ -#define OUR_MAX_SEEK_L 2147483647L - 1L -#define OUR_MAX_SEEK_O 0x7FFFFFFF - 0x1 +#define OUR_MAX_SEEK_L (2147483647L - 1L) +#define OUR_MAX_SEEK_O (0x7FFFFFFF - 0x1) /* The offset check following here is only interesting if curl_off_t is larger than off_t and we are not using the Win32 large file support @@ -55,8 +53,8 @@ int tool_seek_cb(void *userdata, curl_off_t offset, int whence) if(offset > OUR_MAX_SEEK_O) { /* Some precaution code to work around problems with different data sizes - to allow seeking >32-bit even if off_t is 32-bit. Should be very rare - and is really valid on weirdo-systems. */ + to allow seeking >32-bit even if off_t is 32-bit. Should be rare and + is really valid on weirdo-systems. */ curl_off_t left = offset; if(whence != SEEK_SET) @@ -78,7 +76,7 @@ int tool_seek_cb(void *userdata, curl_off_t offset, int whence) } #endif -#if defined(__AMIGA__) || defined(__MINGW32CE__) +#ifdef __AMIGA__ if(LSEEK_ERROR == lseek(per->infd, (off_t)offset, whence)) #else if(LSEEK_ERROR == lseek(per->infd, offset, whence)) diff --git a/src/tool_cb_soc.c b/src/tool_cb_soc.c index d89870297cdb..0df0a1e6fb24 100644 --- a/src/tool_cb_soc.c +++ b/src/tool_cb_soc.c @@ -45,7 +45,7 @@ curl_socket_t tool_socket_open_mptcp_cb(void *clientp, (void)purpose; if(protocol == IPPROTO_TCP) -#if defined(__linux__) +#ifdef __linux__ # ifndef IPPROTO_MPTCP # define IPPROTO_MPTCP 262 # endif diff --git a/src/tool_cb_wrt.c b/src/tool_cb_wrt.c index 724706b7a1af..1b76565399cd 100644 --- a/src/tool_cb_wrt.c +++ b/src/tool_cb_wrt.c @@ -28,8 +28,6 @@ #include "tool_cb_wrt.h" #include "tool_operate.h" -#include "memdebug.h" /* keep this as LAST include */ - #ifdef _WIN32 #define OPENMODE S_IREAD | S_IWRITE #else @@ -68,7 +66,7 @@ bool tool_create_output_file(struct OutStruct *outs, while(fd == -1 && /* have not successfully opened a file */ (errno == EEXIST || errno == EISDIR) && /* because we keep having files that already exist */ - next_num < 100 /* and we have not reached the retry limit */ ) { + next_num < 100 /* and we have not reached the retry limit */) { curlx_dyn_reset(&fbuffer); if(curlx_dyn_addf(&fbuffer, "%s.%d", fname, next_num)) return FALSE; @@ -109,7 +107,7 @@ bool tool_create_output_file(struct OutStruct *outs, return TRUE; } -#if defined(_WIN32) && !defined(UNDER_CE) +#ifdef _WIN32 static size_t win_console(intptr_t fhnd, struct OutStruct *outs, char *buffer, size_t bytes, size_t *retp) @@ -160,12 +158,12 @@ static size_t win_console(intptr_t fhnd, struct OutStruct *outs, } if(complete) { - WCHAR prefix[3] = {0}; /* UTF-16 (1-2 WCHARs) + NUL */ + WCHAR prefix[3] = { 0 }; /* UTF-16 (1-2 WCHARs) + NUL */ if(MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)outs->utf8seq, -1, prefix, CURL_ARRAYSIZE(prefix))) { DEBUGASSERT(prefix[2] == L'\0'); - if(!WriteConsoleW((HANDLE) fhnd, prefix, prefix[1] ? 2 : 1, + if(!WriteConsoleW((HANDLE)fhnd, prefix, prefix[1] ? 2 : 1, &chars_written, NULL)) { return CURL_WRITEFUNC_ERROR; } @@ -211,8 +209,8 @@ static size_t win_console(intptr_t fhnd, struct OutStruct *outs, /* grow the buffer if needed */ if(len > global->term.len) { - wchar_t *buf = (wchar_t *) realloc(global->term.buf, - len * sizeof(wchar_t)); + wchar_t *buf = (wchar_t *)curlx_realloc(global->term.buf, + len * sizeof(wchar_t)); if(!buf) return CURL_WRITEFUNC_ERROR; global->term.len = len; @@ -247,7 +245,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 = global->isatty; -#if defined(_WIN32) && !defined(UNDER_CE) +#ifdef _WIN32 CONSOLE_SCREEN_BUFFER_INFO console_info; intptr_t fhnd; #endif @@ -321,7 +319,7 @@ size_t tool_write_cb(char *buffer, size_t sz, size_t nmemb, void *userdata) } } -#if defined(_WIN32) && !defined(UNDER_CE) +#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)) && diff --git a/src/tool_cfgable.c b/src/tool_cfgable.c index 48148a88ad5b..ab4892b06578 100644 --- a/src/tool_cfgable.c +++ b/src/tool_cfgable.c @@ -28,7 +28,6 @@ #include "tool_paramhlp.h" #include "tool_main.h" #include "tool_msgs.h" -#include "memdebug.h" /* keep this as LAST include */ static struct GlobalConfig globalconf; struct GlobalConfig *global; @@ -36,7 +35,7 @@ struct GlobalConfig *global; struct OperationConfig *config_alloc(void) { struct OperationConfig *config = - calloc(1, sizeof(struct OperationConfig)); + curlx_calloc(1, sizeof(struct OperationConfig)); if(!config) return NULL; @@ -184,8 +183,6 @@ static void free_config_fields(struct OperationConfig *config) tool_safefree(config->ftp_account); tool_safefree(config->ftp_alternative_to_user); tool_safefree(config->aws_sigv4); - tool_safefree(config->proto_str); - tool_safefree(config->proto_redir_str); tool_safefree(config->ech); tool_safefree(config->ech_config); tool_safefree(config->ech_public); @@ -201,7 +198,7 @@ void config_free(struct OperationConfig *config) struct OperationConfig *prev = last->prev; free_config_fields(last); - free(last); + curlx_free(last); last = prev; } @@ -238,12 +235,12 @@ CURLcode globalconf_init(void) if(result) { errorf("error retrieving curl library information"); - free(global->first); + curlx_free(global->first); } } else { errorf("error initializing curl library"); - free(global->first); + curlx_free(global->first); } } else { @@ -262,9 +259,10 @@ static void free_globalconfig(void) curlx_fclose(global->trace_stream); global->trace_stream = NULL; + tool_safefree(global->ssl_sessions); tool_safefree(global->libcurl); -#if defined(_WIN32) && !defined(UNDER_CE) - free(global->term.buf); +#ifdef _WIN32 + curlx_free(global->term.buf); #endif } diff --git a/src/tool_cfgable.h b/src/tool_cfgable.h index 630f23fd9654..6b442dd1c94d 100644 --- a/src/tool_cfgable.h +++ b/src/tool_cfgable.h @@ -24,7 +24,6 @@ * ***************************************************************************/ -#include #include "tool_setup.h" #include "tool_sdecls.h" #include "tool_urlglob.h" @@ -39,10 +38,15 @@ #endif #endif -#define checkprefix(a,b) curl_strnequal(b, STRCONST(a)) +#define MAX_CONFIG_LINE_LENGTH (10 * 1024 * 1024) -#define tool_safefree(ptr) \ - do { free((ptr)); (ptr) = NULL;} while(0) +#define checkprefix(a, b) curl_strnequal(b, STRCONST(a)) + +#define tool_safefree(ptr) \ + do { \ + curlx_free(ptr); \ + (ptr) = NULL; \ + } while(0) extern struct GlobalConfig *global; @@ -248,7 +252,7 @@ struct OperationConfig { BIT(autoreferer); /* automatically set referer */ BIT(show_headers); /* show headers to data output */ BIT(no_body); /* do not get the body */ - BIT(dirlistonly); /* only get the FTP dir list */ + BIT(dirlistonly); /* only get the FTP directory list */ BIT(unrestricted_auth); /* Continue to send authentication (user+password) when following redirects, even when hostname changed */ @@ -326,7 +330,7 @@ struct OperationConfig { BIT(skip_existing); }; -#if defined(_WIN32) && !defined(UNDER_CE) +#ifdef _WIN32 struct termout { wchar_t *buf; DWORD len; @@ -343,7 +347,7 @@ struct GlobalConfig { struct OperationConfig *first; struct OperationConfig *current; struct OperationConfig *last; -#if defined(_WIN32) && !defined(UNDER_CE) +#ifdef _WIN32 struct termout term; #endif timediff_t ms_per_transfer; /* start next transfer after (at least) this diff --git a/src/tool_dirhie.c b/src/tool_dirhie.c index 91cc1b60cbd5..e0eef03a11a3 100644 --- a/src/tool_dirhie.c +++ b/src/tool_dirhie.c @@ -23,17 +23,15 @@ ***************************************************************************/ #include "tool_setup.h" -#if defined(_WIN32) && !defined(UNDER_CE) -# include +#ifdef _WIN32 +#include #endif #include "tool_dirhie.h" #include "tool_msgs.h" -#include "memdebug.h" /* keep this as LAST include */ - #if defined(_WIN32) || (defined(MSDOS) && !defined(__DJGPP__)) -# define mkdir(x,y) (mkdir)((x)) +# define mkdir(x, y) (mkdir)(x) # ifndef F_OK # define F_OK 0 # endif @@ -114,7 +112,7 @@ CURLcode create_dir_hierarchy(const char *outfile) exist, since we would be creating it erroneously. eg if outfile is X:\foo\bar\filename then do not mkdir X: This logic takes into account unsupported drives !:, 1:, etc. */ - if(len > 1 && (outfile[1]==':')) + if(len > 1 && (outfile[1] == ':')) skip = TRUE; } #endif diff --git a/src/tool_doswin.c b/src/tool_doswin.c index 8e9e5f023d39..855ce0897ca1 100644 --- a/src/tool_doswin.c +++ b/src/tool_doswin.c @@ -40,8 +40,6 @@ #include "tool_doswin.h" #include "tool_msgs.h" -#include "memdebug.h" /* keep this as LAST include */ - #ifdef _WIN32 # undef PATH_MAX # define PATH_MAX MAX_PATH @@ -65,14 +63,13 @@ /* only used by msdosify() */ static SANITIZEcode truncate_dryrun(const char *path, const size_t truncate_pos); -static SANITIZEcode msdosify(char **const sanitized, const char *file_name, +static SANITIZEcode msdosify(char ** const sanitized, const char *file_name, int flags); #endif -static SANITIZEcode rename_if_reserved_dos(char **const sanitized, +static SANITIZEcode rename_if_reserved_dos(char ** const sanitized, const char *file_name, int flags); - /* Sanitize a file or path name. @@ -98,7 +95,7 @@ is in a UNC prefixed path. Success: (SANITIZE_ERR_OK) *sanitized points to a sanitized copy of file_name. Failure: (!= SANITIZE_ERR_OK) *sanitized is NULL. */ -SANITIZEcode sanitize_file_name(char **const sanitized, const char *file_name, +SANITIZEcode sanitize_file_name(char ** const sanitized, const char *file_name, int flags) { char *p, *target; @@ -118,22 +115,22 @@ SANITIZEcode sanitize_file_name(char **const sanitized, const char *file_name, #ifndef MSDOS if(file_name[0] == '\\' && file_name[1] == '\\') /* UNC prefixed path \\ (eg \\?\C:\foo) */ - max_sanitized_len = 32767-1; + max_sanitized_len = 32767 - 1; else #endif - max_sanitized_len = PATH_MAX-1; + max_sanitized_len = PATH_MAX - 1; } else /* The maximum length of a filename. FILENAME_MAX is often the same as PATH_MAX, in other words it is 260 and does not discount the path information therefore we should not use it. */ - max_sanitized_len = (PATH_MAX-1 > 255) ? 255 : PATH_MAX-1; + max_sanitized_len = (PATH_MAX - 1 > 255) ? 255 : PATH_MAX - 1; len = strlen(file_name); if(len > max_sanitized_len) return SANITIZE_ERR_INVALID_PATH; - target = strdup(file_name); + target = curlx_strdup(file_name); if(!target) return SANITIZE_ERR_OUT_OF_MEMORY; @@ -183,28 +180,28 @@ SANITIZEcode sanitize_file_name(char **const sanitized, const char *file_name, #ifdef MSDOS sc = msdosify(&p, target, flags); - free(target); + curlx_free(target); if(sc) return sc; target = p; len = strlen(target); if(len > max_sanitized_len) { - free(target); + curlx_free(target); return SANITIZE_ERR_INVALID_PATH; } #endif if(!(flags & SANITIZE_ALLOW_RESERVED)) { sc = rename_if_reserved_dos(&p, target, flags); - free(target); + curlx_free(target); if(sc) return sc; target = p; len = strlen(target); if(len > max_sanitized_len) { - free(target); + curlx_free(target); return SANITIZE_ERR_INVALID_PATH; } } @@ -289,17 +286,18 @@ sanitize_file_name. Success: (SANITIZE_ERR_OK) *sanitized points to a sanitized copy of file_name. Failure: (!= SANITIZE_ERR_OK) *sanitized is NULL. */ -static SANITIZEcode msdosify(char **const sanitized, const char *file_name, +static SANITIZEcode msdosify(char ** const sanitized, const char *file_name, int flags) { char dos_name[PATH_MAX]; - static const char illegal_chars_dos[] = ".+, ;=[]" /* illegal in DOS */ + static const char illegal_chars_dos[] = + ".+, ;=[]" /* illegal in DOS */ "|<>/\\\":?*"; /* illegal in DOS & W95 */ static const char *illegal_chars_w95 = &illegal_chars_dos[8]; int idx, dot_idx; const char *s = file_name; char *d = dos_name; - const char *const dlimit = dos_name + sizeof(dos_name) - 1; + const char * const dlimit = dos_name + sizeof(dos_name) - 1; const char *illegal_aliens = illegal_chars_dos; size_t len = sizeof(illegal_chars_dos) - 1; @@ -311,7 +309,7 @@ static SANITIZEcode msdosify(char **const sanitized, const char *file_name, if(!file_name) return SANITIZE_ERR_BAD_ARGUMENT; - if(strlen(file_name) > PATH_MAX-1) + if(strlen(file_name) > PATH_MAX - 1) return SANITIZE_ERR_INVALID_PATH; /* Support for Windows 9X VFAT systems, when available. */ @@ -324,7 +322,8 @@ static SANITIZEcode msdosify(char **const sanitized, const char *file_name, if(s[0] >= 'A' && s[0] <= 'z' && s[1] == ':') { *d++ = *s++; *d = ((flags & SANITIZE_ALLOW_PATH)) ? ':' : '_'; - ++d; ++s; + ++d; + ++s; } for(idx = 0, dot_idx = -1; *s && d < dlimit; s++, d++) { @@ -375,7 +374,7 @@ static SANITIZEcode msdosify(char **const sanitized, const char *file_name, *d++ = 'x'; if(d == dlimit) break; - *d = 'x'; + *d = 'x'; } else { /* libg++ etc. */ @@ -383,7 +382,7 @@ static SANITIZEcode msdosify(char **const sanitized, const char *file_name, *d++ = 'x'; if(d == dlimit) break; - *d = 'x'; + *d = 'x'; } else { memcpy(d, "plus", 4); @@ -415,7 +414,7 @@ static SANITIZEcode msdosify(char **const sanitized, const char *file_name, return SANITIZE_ERR_INVALID_PATH; } - *sanitized = strdup(dos_name); + *sanitized = curlx_strdup(dos_name); return *sanitized ? SANITIZE_ERR_OK : SANITIZE_ERR_OUT_OF_MEMORY; } #endif /* MSDOS */ @@ -433,7 +432,7 @@ sanitize_file_name. Success: (SANITIZE_ERR_OK) *sanitized points to a sanitized copy of file_name. Failure: (!= SANITIZE_ERR_OK) *sanitized is NULL. */ -static SANITIZEcode rename_if_reserved_dos(char **const sanitized, +static SANITIZEcode rename_if_reserved_dos(char ** const sanitized, const char *file_name, int flags) { @@ -457,14 +456,14 @@ static SANITIZEcode rename_if_reserved_dos(char **const sanitized, #ifndef MSDOS if((flags & SANITIZE_ALLOW_PATH) && file_name[0] == '\\' && file_name[1] == '\\') { - *sanitized = strdup(file_name); + *sanitized = curlx_strdup(file_name); if(!*sanitized) return SANITIZE_ERR_OUT_OF_MEMORY; return SANITIZE_ERR_OK; } #endif - if(len > PATH_MAX-1) + if(len > PATH_MAX - 1) return SANITIZE_ERR_INVALID_PATH; memcpy(fname, file_name, len); @@ -513,7 +512,7 @@ static SANITIZEcode rename_if_reserved_dos(char **const sanitized, p_len = strlen(p); /* Prepend a '_' */ - if(strlen(fname) == PATH_MAX-1) + if(strlen(fname) == PATH_MAX - 1) return SANITIZE_ERR_INVALID_PATH; memmove(p + 1, p, p_len + 1); p[0] = '_'; @@ -536,7 +535,7 @@ static SANITIZEcode rename_if_reserved_dos(char **const sanitized, /* Prepend a '_' */ size_t blen = strlen(base); if(blen) { - if(strlen(fname) >= PATH_MAX-1) + if(strlen(fname) >= PATH_MAX - 1) return SANITIZE_ERR_INVALID_PATH; memmove(base + 1, base, blen + 1); base[0] = '_'; @@ -544,7 +543,7 @@ static SANITIZEcode rename_if_reserved_dos(char **const sanitized, } #endif - *sanitized = strdup(fname); + *sanitized = curlx_strdup(fname); return *sanitized ? SANITIZE_ERR_OK : SANITIZE_ERR_OUT_OF_MEMORY; } @@ -561,7 +560,7 @@ char **__crt0_glob_function(char *arg) #ifdef _WIN32 -#if !defined(CURL_WINDOWS_UWP) && !defined(UNDER_CE) && \ +#if !defined(CURL_WINDOWS_UWP) && \ !defined(CURL_DISABLE_CA_SEARCH) && !defined(CURL_CA_SEARCH_SAFE) /* Search and set the CA cert file for Windows. * @@ -594,11 +593,8 @@ CURLcode FindWin32CACert(struct OperationConfig *config, res_len = SearchPath(NULL, bundle_file, NULL, PATH_MAX, buf, &ptr); if(res_len > 0) { - char *mstr = curlx_convert_tchar_to_UTF8(buf); - tool_safefree(config->cacert); - if(mstr) - config->cacert = strdup(mstr); - curlx_unicodefree(mstr); + curlx_free(config->cacert); + config->cacert = curlx_convert_tchar_to_UTF8(buf); if(!config->cacert) result = CURLE_OUT_OF_MEMORY; } @@ -613,9 +609,9 @@ CURLcode FindWin32CACert(struct OperationConfig *config, struct curl_slist *GetLoadedModulePaths(void) { struct curl_slist *slist = NULL; -#if !defined(CURL_WINDOWS_UWP) && !defined(UNDER_CE) +#ifndef CURL_WINDOWS_UWP HANDLE hnd = INVALID_HANDLE_VALUE; - MODULEENTRY32 mod = {0}; + MODULEENTRY32 mod = { 0 }; mod.dwSize = sizeof(MODULEENTRY32); @@ -664,7 +660,7 @@ struct curl_slist *GetLoadedModulePaths(void) bool tool_term_has_bold; -#if !defined(CURL_WINDOWS_UWP) && !defined(UNDER_CE) +#ifndef CURL_WINDOWS_UWP /* The terminal settings to restore on exit */ static struct TerminalSettings { HANDLE hStdOut; @@ -735,14 +731,14 @@ static void init_terminal(void) CURLcode win32_init(void) { curlx_now_init(); -#if !defined(CURL_WINDOWS_UWP) && !defined(UNDER_CE) +#ifndef CURL_WINDOWS_UWP init_terminal(); #endif return CURLE_OK; } -#if !defined(CURL_WINDOWS_UWP) && !defined(UNDER_CE) +#ifndef CURL_WINDOWS_UWP /* The following STDIN non - blocking read techniques are heavily inspired by nmap and ncat (https://nmap.org/ncat/) */ struct win_thread_data { @@ -765,7 +761,8 @@ static DWORD WINAPI win_stdin_thread_func(void *thread_data) SOCKADDR_IN clientAddr; int clientAddrLen = sizeof(clientAddr); - curl_socket_t socket_w = CURL_ACCEPT(tdata->socket_l, (SOCKADDR*)&clientAddr, + curl_socket_t socket_w = CURL_ACCEPT(tdata->socket_l, + (SOCKADDR *)&clientAddr, &clientAddrLen); if(socket_w == CURL_SOCKET_BAD) { @@ -801,10 +798,7 @@ static DWORD WINAPI win_stdin_thread_func(void *thread_data) if(socket_w != CURL_SOCKET_BAD) sclose(socket_w); - if(tdata) { - free(tdata); - } - + curlx_free(tdata); return 0; } @@ -827,9 +821,10 @@ curl_socket_t win32_stdin_read_thread(void) do { /* Prepare handles for thread */ - tdata = (struct win_thread_data*)calloc(1, sizeof(struct win_thread_data)); + tdata = (struct win_thread_data *) + curlx_calloc(1, sizeof(struct win_thread_data)); if(!tdata) { - errorf("calloc() error"); + errorf("curlx_calloc() error"); break; } /* Create the listening socket for the thread. When it starts, it will @@ -845,14 +840,14 @@ curl_socket_t win32_stdin_read_thread(void) selfaddr.sin_family = AF_INET; selfaddr.sin_addr.S_un.S_addr = htonl(INADDR_LOOPBACK); /* Bind to any available loopback port */ - result = bind(tdata->socket_l, (SOCKADDR*)&selfaddr, socksize); + result = bind(tdata->socket_l, (SOCKADDR *)&selfaddr, socksize); if(result == SOCKET_ERROR) { errorf("bind error: %d", SOCKERRNO); break; } /* Bind to any available loopback port */ - result = getsockname(tdata->socket_l, (SOCKADDR*)&selfaddr, &socksize); + result = getsockname(tdata->socket_l, (SOCKADDR *)&selfaddr, &socksize); if(result == SOCKET_ERROR) { errorf("getsockname error: %d", SOCKERRNO); break; @@ -874,7 +869,7 @@ curl_socket_t win32_stdin_read_thread(void) break; } - /* Start up the thread. We don't bother keeping a reference to it + /* Start up the thread. We do not bother keeping a reference to it because it runs until program termination. From here on out all reads from the stdin handle or file descriptor 0 will be reading from the socket that is fed by the thread. */ @@ -884,6 +879,7 @@ curl_socket_t win32_stdin_read_thread(void) errorf("CreateThread error: 0x%08lx", GetLastError()); break; } + tdata = NULL; /* win_stdin_thread_func owns it now */ /* Connect to the thread and rearrange our own STDIN handles */ socket_r = CURL_SOCKET(AF_INET, SOCK_STREAM, IPPROTO_TCP); @@ -895,7 +891,7 @@ curl_socket_t win32_stdin_read_thread(void) /* Hard close the socket on closesocket() */ setsockopt(socket_r, SOL_SOCKET, SO_DONTLINGER, 0, 0); - if(connect(socket_r, (SOCKADDR*)&selfaddr, socksize) == SOCKET_ERROR) { + if(connect(socket_r, (SOCKADDR *)&selfaddr, socksize) == SOCKET_ERROR) { errorf("connect error: %d", SOCKERRNO); break; } @@ -939,7 +935,7 @@ curl_socket_t win32_stdin_read_thread(void) if(tdata->socket_l != CURL_SOCKET_BAD) sclose(tdata->socket_l); - free(tdata); + curlx_free(tdata); } return CURL_SOCKET_BAD; @@ -949,7 +945,7 @@ curl_socket_t win32_stdin_read_thread(void) return socket_r; } -#endif /* !CURL_WINDOWS_UWP && !UNDER_CE */ +#endif /* !CURL_WINDOWS_UWP */ #endif /* _WIN32 */ diff --git a/src/tool_doswin.h b/src/tool_doswin.h index 7fe5260476ea..75f4bacdb8c2 100644 --- a/src/tool_doswin.h +++ b/src/tool_doswin.h @@ -27,8 +27,8 @@ #if defined(_WIN32) || defined(MSDOS) -#define SANITIZE_ALLOW_PATH (1<<1) /* Allow path separators and colons */ -#define SANITIZE_ALLOW_RESERVED (1<<2) /* Allow reserved device names */ +#define SANITIZE_ALLOW_PATH (1 << 1) /* Allow path separators and colons */ +#define SANITIZE_ALLOW_RESERVED (1 << 2) /* Allow reserved device names */ typedef enum { SANITIZE_ERR_OK = 0, /* 0 - OK */ @@ -38,7 +38,7 @@ typedef enum { SANITIZE_ERR_LAST /* never use! */ } SANITIZEcode; -SANITIZEcode sanitize_file_name(char **const sanitized, const char *file_name, +SANITIZEcode sanitize_file_name(char ** const sanitized, const char *file_name, int flags); #ifdef __DJGPP__ @@ -47,7 +47,7 @@ char **__crt0_glob_function(char *arg); #ifdef _WIN32 -#if !defined(CURL_WINDOWS_UWP) && !defined(UNDER_CE) && \ +#if !defined(CURL_WINDOWS_UWP) && \ !defined(CURL_DISABLE_CA_SEARCH) && !defined(CURL_CA_SEARCH_SAFE) CURLcode FindWin32CACert(struct OperationConfig *config, const TCHAR *bundle_file); @@ -55,9 +55,9 @@ CURLcode FindWin32CACert(struct OperationConfig *config, struct curl_slist *GetLoadedModulePaths(void); CURLcode win32_init(void); -#if !defined(CURL_WINDOWS_UWP) && !defined(UNDER_CE) +#ifndef CURL_WINDOWS_UWP curl_socket_t win32_stdin_read_thread(void); -#endif /* !CURL_WINDOWS_UWP && !UNDER_CE */ +#endif #endif /* _WIN32 */ diff --git a/src/tool_easysrc.c b/src/tool_easysrc.c index 65d01d5f85a6..ba9d345645c0 100644 --- a/src/tool_easysrc.c +++ b/src/tool_easysrc.c @@ -31,8 +31,6 @@ #include "tool_easysrc.h" #include "tool_msgs.h" -#include "memdebug.h" /* keep this as LAST include */ - /* global variable definitions, for easy-interface source code generation */ struct slist_wc *easysrc_decl; /* Variable declarations */ @@ -43,7 +41,7 @@ struct slist_wc *easysrc_clean; /* Clean up allocated data */ int easysrc_mime_count; int easysrc_slist_count; -static const char *const srchead[]={ +static const char * const srchead[] = { "/********* Sample code generated by the curl command line tool **********", " * All curl_easy_setopt() options are documented at:", " * https://curl.se/libcurl/c/curl_easy_setopt.html", @@ -59,7 +57,7 @@ static const char *const srchead[]={ /* easysrc_decl declarations come here */ /* easysrc_data initialization come here */ /* easysrc_code statements come here */ -static const char *const srchard[]={ +static const char * const srchard[] = { "/* Here is a list of options the curl code used that cannot get generated", " as source easily. You may choose to either not use them or implement", " them yourself.", diff --git a/src/tool_filetime.c b/src/tool_filetime.c index 6dc2fbbe4234..afe308f8ad68 100644 --- a/src/tool_filetime.c +++ b/src/tool_filetime.c @@ -41,18 +41,14 @@ int getfiletime(const char *filename, curl_off_t *stamp) access to a 64-bit type we can bypass stat and get the times directly. */ #if defined(_WIN32) && !defined(CURL_WINDOWS_UWP) HANDLE hfile; - TCHAR *tchar_filename = curlx_convert_UTF8_to_tchar(filename); - - hfile = CreateFile(tchar_filename, FILE_READ_ATTRIBUTES, - (FILE_SHARE_READ | FILE_SHARE_WRITE | - FILE_SHARE_DELETE), - NULL, OPEN_EXISTING, 0, NULL); - curlx_unicodefree(tchar_filename); + hfile = curlx_CreateFile(filename, FILE_READ_ATTRIBUTES, + FILE_SHARE_READ | FILE_SHARE_WRITE | + FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL); if(hfile != INVALID_HANDLE_VALUE) { FILETIME ft; if(GetFileTime(hfile, NULL, NULL, &ft)) { - curl_off_t converted = (curl_off_t)ft.dwLowDateTime - | ((curl_off_t)ft.dwHighDateTime) << 32; + curl_off_t converted = (curl_off_t)ft.dwLowDateTime | + ((curl_off_t)ft.dwHighDateTime) << 32; if(converted < 116444736000000000) warnf("Failed to get filetime: underflow"); @@ -94,22 +90,23 @@ void setfiletime(curl_off_t filetime, const char *filename) access to a 64-bit type we can bypass utime and set the times directly. */ #if defined(_WIN32) && !defined(CURL_WINDOWS_UWP) HANDLE hfile; - TCHAR *tchar_filename = curlx_convert_UTF8_to_tchar(filename); - /* 910670515199 is the maximum Unix filetime that can be used as a - Windows FILETIME without overflow: 30827-12-31T23:59:59. */ + /* 910670515199 is the maximum Unix filetime that can be used as a Windows + FILETIME without overflow: 30827-12-31T23:59:59. */ if(filetime > 910670515199) { - warnf("Failed to set filetime %" CURL_FORMAT_CURL_OFF_T - " on outfile: overflow", filetime); - curlx_unicodefree(tchar_filename); - return; + filetime = 910670515199; + warnf("Capping set filetime to max to avoid overflow"); + } + else if(filetime < -6857222400) { + /* dates before 14 september 1752 (pre-Gregorian calendar) are not + accurate */ + filetime = -6857222400; + warnf("Capping set filetime to minimum to avoid overflow"); } - hfile = CreateFile(tchar_filename, FILE_WRITE_ATTRIBUTES, - (FILE_SHARE_READ | FILE_SHARE_WRITE | - FILE_SHARE_DELETE), - NULL, OPEN_EXISTING, 0, NULL); - curlx_unicodefree(tchar_filename); + hfile = curlx_CreateFile(filename, FILE_WRITE_ATTRIBUTES, + FILE_SHARE_READ | FILE_SHARE_WRITE | + FILE_SHARE_DELETE, NULL, OPEN_EXISTING, 0, NULL); if(hfile != INVALID_HANDLE_VALUE) { curl_off_t converted = ((curl_off_t)filetime * 10000000) + 116444736000000000; diff --git a/src/tool_filetime.h b/src/tool_filetime.h index c3663617b533..fedb7a195792 100644 --- a/src/tool_filetime.h +++ b/src/tool_filetime.h @@ -31,7 +31,7 @@ int getfiletime(const char *filename, curl_off_t *stamp); (defined(_WIN32) && (SIZEOF_CURL_OFF_T >= 8)) void setfiletime(curl_off_t filetime, const char *filename); #else -#define setfiletime(a,b,c) tool_nop_stmt +#define setfiletime(a, b, c) tool_nop_stmt #endif #endif /* HEADER_CURL_TOOL_FILETIME_H */ diff --git a/src/tool_findfile.c b/src/tool_findfile.c index 02898a8fb1b5..c962eb86b8cb 100644 --- a/src/tool_findfile.c +++ b/src/tool_findfile.c @@ -36,8 +36,6 @@ #include "tool_findfile.h" #include "tool_cfgable.h" -#include "memdebug.h" /* keep this as LAST include */ - struct finder { const char *env; const char *append; @@ -53,7 +51,7 @@ static const struct finder conf_list[] = { #ifdef _WIN32 { "USERPROFILE", NULL, FALSE }, { "APPDATA", NULL, FALSE }, - { "USERPROFILE", "\\Application Data", FALSE}, + { "USERPROFILE", "\\Application Data", FALSE }, #endif /* these are for .curlrc if XDG_CONFIG_HOME is not defined */ { "CURL_HOME", "/.config", TRUE }, @@ -75,7 +73,7 @@ static char *checkhome(const char *home, const char *fname, bool dotscore) if(c) { int fd = curlx_open(c, O_RDONLY); if(fd >= 0) { - char *path = strdup(c); + char *path = curlx_strdup(c); close(fd); curl_free(c); return path; @@ -87,7 +85,8 @@ static char *checkhome(const char *home, const char *fname, bool dotscore) } /* - * findfile() - return the full path name of the file. + * findfile() - returns the full path name of the file. It must be freed with + * curl_free(). * * If 'dotscore' is TRUE, then check for the file first with a leading dot * and then with a leading underscore. diff --git a/src/tool_formparse.c b/src/tool_formparse.c index cd3cf52e3ebd..31b381d7e0f1 100644 --- a/src/tool_formparse.c +++ b/src/tool_formparse.c @@ -28,14 +28,13 @@ #include "tool_getparam.h" #include "tool_paramhlp.h" #include "tool_formparse.h" - -#include "memdebug.h" /* keep this as LAST include */ +#include "tool_parsecfg.h" /* tool_mime functions. */ static struct tool_mime *tool_mime_new(struct tool_mime *parent, toolmimekind kind) { - struct tool_mime *m = (struct tool_mime *) calloc(1, sizeof(*m)); + struct tool_mime *m = (struct tool_mime *)curlx_calloc(1, sizeof(*m)); if(m) { m->kind = kind; @@ -59,11 +58,11 @@ static struct tool_mime *tool_mime_new_data(struct tool_mime *parent, char *mime_data_copy; struct tool_mime *m = NULL; - mime_data_copy = strdup(mime_data); + mime_data_copy = curlx_strdup(mime_data); if(mime_data_copy) { m = tool_mime_new(parent, TOOLMIME_DATA); if(!m) - free(mime_data_copy); + curlx_free(mime_data_copy); else m->data = mime_data_copy; } @@ -87,8 +86,8 @@ static curl_off_t uztoso(size_t uznum) # pragma warning(disable:4310) /* cast truncates constant value */ #endif - DEBUGASSERT(uznum <= (size_t) CURL_MASK_SCOFFT); - return (curl_off_t)(uznum & (size_t) CURL_MASK_SCOFFT); + DEBUGASSERT(uznum <= (size_t)CURL_MASK_SCOFFT); + return (curl_off_t)(uznum & (size_t)CURL_MASK_SCOFFT); #if defined(__INTEL_COMPILER) || defined(_MSC_VER) # pragma warning(pop) @@ -106,25 +105,21 @@ static struct tool_mime *tool_mime_new_filedata(struct tool_mime *parent, *errcode = CURLE_OUT_OF_MEMORY; if(strcmp(filename, "-")) { /* This is a normal file. */ - char *filedup = strdup(filename); + char *filedup = curlx_strdup(filename); if(filedup) { m = tool_mime_new(parent, TOOLMIME_FILE); if(!m) - free(filedup); + curlx_free(filedup); else { m->data = filedup; if(!isremotefile) m->kind = TOOLMIME_FILEDATA; - *errcode = CURLE_OK; + *errcode = CURLE_OK; } } } else { /* Standard input. */ -#ifdef UNDER_CE - int fd = STDIN_FILENO; -#else int fd = fileno(stdin); -#endif char *data = NULL; curl_off_t size; curl_off_t origin; @@ -155,7 +150,7 @@ static struct tool_mime *tool_mime_new_filedata(struct tool_mime *parent, default: if(!stdinsize) { /* Zero-length data has been freed. Re-create it. */ - data = strdup(""); + data = curlx_strdup(""); if(!data) return m; } @@ -193,16 +188,15 @@ void tool_mime_free(struct tool_mime *mime) tool_safefree(mime->encoder); tool_safefree(mime->data); curl_slist_free_all(mime->headers); - free(mime); + curlx_free(mime); } } - /* Mime part callbacks for stdin. */ size_t tool_mime_stdin_read(char *buffer, size_t size, size_t nitems, void *arg) { - struct tool_mime *sip = (struct tool_mime *) arg; + struct tool_mime *sip = (struct tool_mime *)arg; curl_off_t bytesleft; (void)size; /* Always 1: ignored. */ @@ -235,7 +229,7 @@ size_t tool_mime_stdin_read(char *buffer, int tool_mime_stdin_seek(void *instream, curl_off_t offset, int whence) { - struct tool_mime *sip = (struct tool_mime *) instream; + struct tool_mime *sip = (struct tool_mime *)instream; switch(whence) { case SEEK_CUR: @@ -248,7 +242,7 @@ int tool_mime_stdin_seek(void *instream, curl_off_t offset, int whence) if(offset < 0) return CURL_SEEKFUNC_CANTSEEK; if(!sip->data) { - if(fseek(stdin, (long) (offset + sip->origin), SEEK_SET)) + if(curlx_fseek(stdin, offset + sip->origin, SEEK_SET)) return CURL_SEEKFUNC_CANTSEEK; } sip->curpos = offset; @@ -301,8 +295,8 @@ static CURLcode tool2curlparts(CURL *curl, struct tool_mime *m, FALLTHROUGH(); case TOOLMIME_STDINDATA: ret = curl_mime_data_cb(part, m->size, - (curl_read_callback) tool_mime_stdin_read, - (curl_seek_callback) tool_mime_stdin_seek, + (curl_read_callback)tool_mime_stdin_read, + (curl_seek_callback)tool_mime_stdin_seek, NULL, m); break; @@ -377,8 +371,7 @@ static char *get_param_word(char **str, char **end_pos, char endchar) if(*ptr == '\\' && (ptr[1] == '\\' || ptr[1] == '"')) ++ptr; *ptr2++ = *ptr++; - } - while(ptr < *end_pos); + } while(ptr < *end_pos); *end_pos = ptr2; } ++ptr; @@ -417,65 +410,63 @@ static int slist_append(struct curl_slist **plist, const char *data) } /* Read headers from a file and append to list. */ -static int read_field_headers(const char *filename, FILE *fp, - struct curl_slist **pheaders) +static int read_field_headers(FILE *fp, struct curl_slist **pheaders) { - size_t hdrlen = 0; - size_t pos = 0; - bool incomment = FALSE; - int lineno = 1; - char hdrbuf[999] = ""; /* Max. header length + 1. */ - - for(;;) { - int c = getc(fp); - if(c == EOF || (!pos && !ISSPACE(c))) { - /* Strip and flush the current header. */ - while(hdrlen && ISSPACE(hdrbuf[hdrlen - 1])) - hdrlen--; - if(hdrlen) { - hdrbuf[hdrlen] = '\0'; - if(slist_append(pheaders, hdrbuf)) { - errorf("Out of memory for field headers"); - return -1; - } - hdrlen = 0; - } - } - - switch(c) { - case EOF: - if(ferror(fp)) { - char errbuf[STRERROR_LEN]; - errorf("Header file %s read error: %s", filename, - curlx_strerror(errno, errbuf, sizeof(errbuf))); - return -1; - } - return 0; /* Done. */ - case '\r': - continue; /* Ignore. */ - case '\n': - pos = 0; - incomment = FALSE; - lineno++; + struct dynbuf line; + bool error = FALSE; + int err = 0; + + curlx_dyn_init(&line, 8092); + while(my_get_line(fp, &line, &error)) { + const char *ptr = curlx_dyn_ptr(&line); + size_t len = curlx_dyn_len(&line); + bool folded = FALSE; + if(ptr[0] == '#') /* comment */ continue; - case '#': - if(!pos) - incomment = TRUE; - break; - } + else if(ptr[0] == ' ') /* a continuation from the line before */ + folded = TRUE; + /* trim off trailing CRLFs and whitespaces */ + while(len && (ISNEWLINE(ptr[len - 1]) || ISBLANK(ptr[len - 1]))) + len--; - pos++; - if(!incomment) { - if(hdrlen == sizeof(hdrbuf) - 1) { - warnf("File %s line %d: header too long (truncated)", - filename, lineno); - c = ' '; + if(!len) + continue; + curlx_dyn_setlen(&line, len); /* set the new length */ + + if(folded && *pheaders) { + /* append this new line onto the previous line */ + struct dynbuf amend; + struct curl_slist *l = *pheaders; + curlx_dyn_init(&amend, 8092); + /* find the last node */ + while(l && l->next) + l = l->next; + /* add both parts */ + if(curlx_dyn_add(&amend, l->data) || curlx_dyn_addn(&amend, ptr, len)) { + err = -1; + break; + } + curl_free(l->data); + /* we use maprintf here to make it a libcurl alloc, to match the previous + curl_slist_append */ + l->data = curl_maprintf("%s", curlx_dyn_ptr(&amend)); + curlx_dyn_free(&amend); + if(!l->data) { + errorf("Out of memory for field headers"); + err = 1; } - if(hdrlen <= sizeof(hdrbuf) - 1) - hdrbuf[hdrlen++] = (char) c; + } + else { + err = slist_append(pheaders, ptr); + } + if(err) { + errorf("Out of memory for field headers"); + err = -1; + break; } } - /* NOTREACHED */ + curlx_dyn_free(&line); + return err; } static int get_param_part(char endchar, @@ -572,7 +563,7 @@ static int get_param_part(char endchar, curlx_strerror(errno, errbuf, sizeof(errbuf))); } else { - int i = read_field_headers(hdrfile, fp, &headers); + int i = read_field_headers(fp, &headers); curlx_fclose(fp); if(i) { @@ -665,7 +656,6 @@ static int get_param_part(char endchar, return sep & 0xFF; } - /*************************************************************************** * * formparse() @@ -713,13 +703,13 @@ static int get_param_part(char endchar, * ***************************************************************************/ -#define SET_TOOL_MIME_PTR(m, field) \ - do { \ - if(field) { \ - (m)->field = strdup(field); \ - if(!(m)->field) \ - goto fail; \ - } \ +#define SET_TOOL_MIME_PTR(m, field) \ + do { \ + if(field) { \ + (m)->field = curlx_strdup(field); \ + if(!(m)->field) \ + goto fail; \ + } \ } while(0) int formparse(const char *input, @@ -750,7 +740,7 @@ int formparse(const char *input, } /* Make a copy we can overwrite. */ - contents = strdup(input); + contents = curlx_strdup(input); if(!contents) goto fail; @@ -818,9 +808,8 @@ int formparse(const char *input, part->headers = headers; headers = NULL; if(res == CURLE_READ_ERROR) { - /* An error occurred while reading stdin: if read has started, - issue the error now. Else, delay it until processed by - libcurl. */ + /* An error occurred while reading stdin: if read has started, + issue the error now. Else, delay it until processed by libcurl. */ if(part->size > 0) { warnf("error while reading standard input"); goto fail; @@ -845,16 +834,15 @@ int formparse(const char *input, if(sep < 0) goto fail; - part = tool_mime_new_filedata(*mimecurrent, data, FALSE, - &res); + part = tool_mime_new_filedata(*mimecurrent, data, FALSE, &res); if(!part) goto fail; part->headers = headers; headers = NULL; if(res == CURLE_READ_ERROR) { - /* An error occurred while reading stdin: if read has started, - issue the error now. Else, delay it until processed by - libcurl. */ + /* An error occurred while reading stdin: if read has started, + issue the error now. Else, delay it until processed by + libcurl. */ if(part->size > 0) { warnf("error while reading standard input"); goto fail; @@ -886,7 +874,7 @@ int formparse(const char *input, SET_TOOL_MIME_PTR(part, encoder); if(sep) { - *contp = (char) sep; + *contp = (char)sep; warnf("garbage at end of field specification: %s", contp); } } diff --git a/src/tool_getparam.c b/src/tool_getparam.c index 0cff5b558d9b..89385af84436 100644 --- a/src/tool_getparam.c +++ b/src/tool_getparam.c @@ -38,22 +38,20 @@ #include "tool_help.h" #include "var.h" -#include "memdebug.h" /* keep this as LAST include */ - #define ALLOW_BLANK TRUE -#define DENY_BLANK FALSE +#define DENY_BLANK FALSE static ParameterError getstr(char **str, const char *val, bool allowblank) { if(*str) { - free(*str); + curlx_free(*str); *str = NULL; } DEBUGASSERT(val); if(!allowblank && !val[0]) return PARAM_BLANK_STRING; - *str = strdup(val); + *str = curlx_strdup(val); if(!*str) return PARAM_NO_MEM; @@ -64,14 +62,14 @@ static ParameterError getstrn(char **str, const char *val, size_t len, bool allowblank) { if(*str) { - free(*str); + curlx_free(*str); *str = NULL; } DEBUGASSERT(val); if(!allowblank && !val[0]) return PARAM_BLANK_STRING; - *str = malloc(len + 1); + *str = curlx_malloc(len + 1); if(!*str) return PARAM_NO_MEM; @@ -385,20 +383,21 @@ static const struct LongShort aliases[]= { #ifndef UNITTESTS static #endif -void parse_cert_parameter(const char *cert_parameter, - char **certname, - char **passphrase) +ParameterError parse_cert_parameter(const char *cert_parameter, + char **certname, + char **passphrase) { size_t param_length = strlen(cert_parameter); size_t span; const char *param_place = NULL; char *certname_place = NULL; + ParameterError err = PARAM_OK; *certname = NULL; *passphrase = NULL; /* most trivial assumption: cert_parameter is empty */ if(param_length == 0) - return; + return PARAM_BLANK_STRING; /* next less trivial: cert_parameter starts 'pkcs11:' and thus * looks like a RFC7512 PKCS#11 URI which can be used as-is. @@ -406,13 +405,17 @@ void parse_cert_parameter(const char *cert_parameter, * means no passphrase was given and no characters escaped */ if(curl_strnequal(cert_parameter, "pkcs11:", 7) || !strpbrk(cert_parameter, ":\\")) { - *certname = strdup(cert_parameter); - return; + *certname = curlx_strdup(cert_parameter); + if(!*certname) + return PARAM_NO_MEM; + return PARAM_OK; } /* deal with escaped chars; find unescaped colon if it exists */ - certname_place = malloc(param_length + 1); - if(!certname_place) - return; + certname_place = curlx_malloc(param_length + 1); + if(!certname_place) { + err = PARAM_NO_MEM; + goto done; + } *certname = certname_place; param_place = cert_parameter; @@ -429,22 +432,22 @@ void parse_cert_parameter(const char *cert_parameter, case '\\': param_place++; switch(*param_place) { - case '\0': - *certname_place++ = '\\'; - break; - case '\\': - *certname_place++ = '\\'; - param_place++; - break; - case ':': - *certname_place++ = ':'; - param_place++; - break; - default: - *certname_place++ = '\\'; - *certname_place++ = *param_place; - param_place++; - break; + case '\0': + *certname_place++ = '\\'; + break; + case '\\': + *certname_place++ = '\\'; + param_place++; + break; + case ':': + *certname_place++ = ':'; + param_place++; + break; + default: + *certname_place++ = '\\'; + *certname_place++ = *param_place; + param_place++; + break; } break; case ':': @@ -456,7 +459,7 @@ void parse_cert_parameter(const char *cert_parameter, #ifdef _WIN32 if((param_place == &cert_parameter[1]) && (cert_parameter[2] == '\\' || cert_parameter[2] == '/') && - (ISALPHA(cert_parameter[0])) ) { + (ISALPHA(cert_parameter[0]))) { /* colon in the second column, followed by a backslash, and the first character is an alphabetic letter: @@ -470,13 +473,20 @@ void parse_cert_parameter(const char *cert_parameter, * above; if we are still here, this is a separating colon */ param_place++; if(*param_place) { - *passphrase = strdup(param_place); + *passphrase = curlx_strdup(param_place); + if(!*passphrase) + err = PARAM_NO_MEM; } goto done; } } done: - *certname_place = '\0'; + if(err) { + tool_safefree(*certname); + } + else + *certname_place = '\0'; + return err; } /* Replace (in-place) '%20' by '+' according to RFC1866 */ @@ -493,7 +503,7 @@ static size_t replace_url_encoded_space_by_plus(char *url) url[new_index] = '+'; orig_index += 3; } - else{ + else { if(new_index != orig_index) { url[new_index] = url[orig_index]; } @@ -507,18 +517,22 @@ static size_t replace_url_encoded_space_by_plus(char *url) return new_index; /* new size */ } -static void -GetFileAndPassword(const char *nextarg, char **file, char **password) +static ParameterError GetFileAndPassword(const char *nextarg, char **file, + char **password) { char *certname, *passphrase; + ParameterError err; /* nextarg is never NULL here */ - parse_cert_parameter(nextarg, &certname, &passphrase); - free(*file); - *file = certname; - if(passphrase) { - free(*password); - *password = passphrase; + err = parse_cert_parameter(nextarg, &certname, &passphrase); + if(!err) { + curlx_free(*file); + *file = certname; + if(passphrase) { + curlx_free(*password); + *password = passphrase; + } } + return err; } /* Get a size parameter for '--limit-rate' or '--max-filesize'. @@ -544,15 +558,15 @@ static ParameterError GetSizeParameter(const char *arg, switch(*unit) { case 'G': case 'g': - if(value > (CURL_OFF_T_MAX / (1024*1024*1024))) + if(value > (CURL_OFF_T_MAX / (1024 * 1024 * 1024))) return PARAM_NUMBER_TOO_LARGE; - value *= 1024*1024*1024; + value *= 1024 * 1024 * 1024; break; case 'M': case 'm': - if(value > (CURL_OFF_T_MAX / (1024*1024))) + if(value > (CURL_OFF_T_MAX / (1024 * 1024))) return PARAM_NUMBER_TOO_LARGE; - value *= 1024*1024; + value *= 1024 * 1024; break; case 'K': case 'k': @@ -588,7 +602,7 @@ static void cleanarg(char *str) #endif /* the maximum size we allow the dynbuf generated string */ -#define MAX_DATAURLENCODE (500*1024*1024) +#define MAX_DATAURLENCODE (500 * 1024 * 1024) /* --data-urlencode */ static ParameterError data_urlencode(const char *nextarg, @@ -652,7 +666,7 @@ static ParameterError data_urlencode(const char *nextarg, if(!postdata) { /* no data from the file, point to a zero byte string to make this get sent as a POST anyway */ - postdata = strdup(""); + postdata = curlx_strdup(""); if(!postdata) return PARAM_NO_MEM; size = 0; @@ -692,8 +706,7 @@ static ParameterError data_urlencode(const char *nextarg, return err; } -static void sethttpver(struct OperationConfig *config, - long httpversion) +static void sethttpver(struct OperationConfig *config, long httpversion) { if(config->httpversion && (config->httpversion != httpversion)) @@ -718,20 +731,20 @@ static CURLcode set_trace_config(const char *token) len = strlen(token); switch(*token) { - case '-': - toggle = FALSE; - name = token + 1; - len--; - break; - case '+': - toggle = TRUE; - name = token + 1; - len--; - break; - default: - toggle = TRUE; - name = token; - break; + case '-': + toggle = FALSE; + name = token + 1; + len--; + break; + case '+': + toggle = TRUE; + name = token + 1; + len--; + break; + default: + toggle = TRUE; + name = token; + break; } if((len == 3) && curl_strnequal(name, "all", 3)) { @@ -802,37 +815,37 @@ struct TOSEntry { }; static const struct TOSEntry tos_entries[] = { - {"AF11", 0x28}, - {"AF12", 0x30}, - {"AF13", 0x38}, - {"AF21", 0x48}, - {"AF22", 0x50}, - {"AF23", 0x58}, - {"AF31", 0x68}, - {"AF32", 0x70}, - {"AF33", 0x78}, - {"AF41", 0x88}, - {"AF42", 0x90}, - {"AF43", 0x98}, - {"CE", 0x03}, - {"CS0", 0x00}, - {"CS1", 0x20}, - {"CS2", 0x40}, - {"CS3", 0x60}, - {"CS4", 0x80}, - {"CS5", 0xa0}, - {"CS6", 0xc0}, - {"CS7", 0xe0}, - {"ECT0", 0x02}, - {"ECT1", 0x01}, - {"EF", 0xb8}, - {"LE", 0x04}, - {"LOWCOST", 0x02}, - {"LOWDELAY", 0x10}, - {"MINCOST", 0x02}, - {"RELIABILITY", 0x04}, - {"THROUGHPUT", 0x08}, - {"VOICE-ADMIT", 0xb0} + { "AF11", 0x28 }, + { "AF12", 0x30 }, + { "AF13", 0x38 }, + { "AF21", 0x48 }, + { "AF22", 0x50 }, + { "AF23", 0x58 }, + { "AF31", 0x68 }, + { "AF32", 0x70 }, + { "AF33", 0x78 }, + { "AF41", 0x88 }, + { "AF42", 0x90 }, + { "AF43", 0x98 }, + { "CE", 0x03 }, + { "CS0", 0x00 }, + { "CS1", 0x20 }, + { "CS2", 0x40 }, + { "CS3", 0x60 }, + { "CS4", 0x80 }, + { "CS5", 0xa0 }, + { "CS6", 0xc0 }, + { "CS7", 0xe0 }, + { "ECT0", 0x02 }, + { "ECT1", 0x01 }, + { "EF", 0xb8 }, + { "LE", 0x04 }, + { "LOWCOST", 0x02 }, + { "LOWDELAY", 0x10 }, + { "MINCOST", 0x02 }, + { "RELIABILITY", 0x04 }, + { "THROUGHPUT", 0x08 }, + { "VOICE-ADMIT", 0xb0 } }; static int find_tos(const void *a, const void *b) @@ -854,7 +867,7 @@ static ParameterError url_query(const char *nextarg, if(*nextarg == '+') { /* use without encoding */ - query = strdup(&nextarg[1]); + query = curlx_strdup(&nextarg[1]); if(!query) err = PARAM_NO_MEM; } @@ -864,11 +877,11 @@ static ParameterError url_query(const char *nextarg, if(!err) { if(config->query) { CURLcode result = curlx_dyn_addf(&dyn, "%s&%s", config->query, query); - free(query); + curlx_free(query); if(result) err = PARAM_NO_MEM; else { - free(config->query); + curlx_free(config->query); config->query = curlx_dyn_ptr(&dyn); } } @@ -928,7 +941,7 @@ static ParameterError set_data(cmdline_t cmd, if(!postdata) { /* no data from the file, point to a zero byte string to make this get sent as a POST anyway */ - postdata = strdup(""); + postdata = curlx_strdup(""); if(!postdata) return PARAM_NO_MEM; } @@ -972,9 +985,9 @@ static ParameterError set_rate(const char *nextarg) const char *div = strchr(nextarg, '/'); char number[26]; long denominator; - long numerator = 60*60*1000; /* default per hour */ + long numerator = 60 * 60 * 1000; /* default per hour */ size_t numlen = div ? (size_t)(div - nextarg) : strlen(nextarg); - if(numlen > sizeof(number) -1) + if(numlen > sizeof(number) - 1) return PARAM_NUMBER_TOO_LARGE; memcpy(number, nextarg, numlen); @@ -998,12 +1011,12 @@ static ParameterError set_rate(const char *nextarg) numerator = 1000; break; case 'm': /* per minute */ - numerator = 60*1000; + numerator = 60 * 1000; break; case 'h': /* per hour */ break; case 'd': /* per day */ - numerator = 24*60*60*1000; + numerator = 24 * 60 * 60 * 1000; break; default: errorf("unsupported --rate unit"); @@ -1026,7 +1039,7 @@ static ParameterError set_rate(const char *nextarg) else if(denominator > numerator) err = PARAM_NUMBER_TOO_LARGE; else - global->ms_per_transfer = numerator/denominator; + global->ms_per_transfer = numerator / denominator; return err; } @@ -1119,7 +1132,6 @@ static ParameterError parse_url(struct OperationConfig *config, return add_url(config, nextarg, FALSE); } - static ParameterError parse_localport(struct OperationConfig *config, const char *nextarg) { @@ -1149,7 +1161,7 @@ static ParameterError parse_localport(struct OperationConfig *config, else { if(str2unummax(&config->localportrange, pp, 65535)) return PARAM_BAD_USE; - config->localportrange -= (config->localport-1); + config->localportrange -= (config->localport - 1); if(config->localportrange < 1) return PARAM_BAD_USE; } @@ -1213,7 +1225,7 @@ static ParameterError parse_ech(struct OperationConfig *config, file = curlx_fopen(nextarg, FOPEN_READTEXT); } if(!file) { - warnf("Couldn't read file \"%s\" " + warnf("Could not read file \"%s\" " "specified for \"--ech ecl:\" option", nextarg); return PARAM_BAD_USE; /* */ @@ -1223,8 +1235,8 @@ static ParameterError parse_ech(struct OperationConfig *config, curlx_fclose(file); if(err) return err; - config->ech_config = curl_maprintf("ecl:%s",tmpcfg); - free(tmpcfg); + config->ech_config = curl_maprintf("ecl:%s", tmpcfg); + curlx_free(tmpcfg); if(!config->ech_config) return PARAM_NO_MEM; } /* file done */ @@ -1254,7 +1266,7 @@ static ParameterError parse_header(struct OperationConfig *config, else { struct dynbuf line; bool error = FALSE; - curlx_dyn_init(&line, 1024*100); + curlx_dyn_init(&line, 1024 * 100); while(my_get_line(file, &line, &error)) { const char *ptr = curlx_dyn_ptr(&line); err = add2list(cmd == C_PROXY_HEADER ? /* --proxy-header? */ @@ -1273,7 +1285,7 @@ static ParameterError parse_header(struct OperationConfig *config, else { if(!strchr(nextarg, ':') && !strchr(nextarg, ';')) { warnf("The provided %s header '%s' does not look like a header?", - (cmd == C_PROXY_HEADER) ? "proxy": "HTTP", nextarg); + (cmd == C_PROXY_HEADER) ? "proxy" : "HTTP", nextarg); } if(cmd == C_PROXY_HEADER) /* --proxy-header */ err = add2list(&config->proxyheaders, nextarg); @@ -1400,7 +1412,7 @@ static ParameterError parse_range(struct OperationConfig *config, if(!curlx_str_number(&nextarg, &value, CURL_OFF_T_MAX) && curlx_str_single(&nextarg, '-')) { /* Specifying a range WITHOUT A DASH will create an illegal HTTP range - (and will not actually be range by definition). The manpage previously + (and will not 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. */ char buffer[32]; @@ -1408,8 +1420,8 @@ static ParameterError parse_range(struct OperationConfig *config, "Appending one for you"); curl_msnprintf(buffer, sizeof(buffer), "%" CURL_FORMAT_CURL_OFF_T "-", value); - free(config->range); - config->range = strdup(buffer); + curlx_free(config->range); + config->range = curlx_strdup(buffer); if(!config->range) err = PARAM_NO_MEM; } @@ -1493,8 +1505,8 @@ static ParameterError parse_verbose(bool toggle) switch(global->verbosity) { case 0: global->verbosity = 1; - free(global->trace_dump); - global->trace_dump = strdup("%"); + curlx_free(global->trace_dump); + global->trace_dump = curlx_strdup("%"); if(!global->trace_dump) err = PARAM_NO_MEM; else { @@ -1615,12 +1627,12 @@ struct flagmap { }; static const struct flagmap flag_table[] = { - {"answered", 8, CURLULFLAG_ANSWERED}, - {"deleted", 7, CURLULFLAG_DELETED}, - {"draft", 5, CURLULFLAG_DRAFT}, - {"flagged", 7, CURLULFLAG_FLAGGED}, - {"seen", 4, CURLULFLAG_SEEN}, - {NULL, 0, 0} + { "answered", 8, CURLULFLAG_ANSWERED }, + { "deleted", 7, CURLULFLAG_DELETED }, + { "draft", 5, CURLULFLAG_DRAFT }, + { "flagged", 7, CURLULFLAG_FLAGGED }, + { "seen", 4, CURLULFLAG_SEEN }, + { NULL, 0, 0 } }; static ParameterError parse_upload_flags(struct OperationConfig *config, @@ -1654,15 +1666,15 @@ static ParameterError parse_upload_flags(struct OperationConfig *config, } } - if(!map->name) { - err = PARAM_OPTION_UNKNOWN; - break; - } + if(!map->name) { + err = PARAM_OPTION_UNKNOWN; + break; + } - if(next) - /* move over the comma */ - next++; - flag = next; + if(next) + /* move over the comma */ + next++; + flag = next; } return err; @@ -2084,7 +2096,7 @@ static ParameterError opt_bool(struct OperationConfig *config, config->doh_insecure_ok = toggle; break; case C_LIST_ONLY: /* --list-only */ - config->dirlistonly = toggle; /* only list the names of the FTP dir */ + config->dirlistonly = toggle; /* only list names of the FTP directory */ break; case C_MANUAL: /* --manual */ if(toggle) /* --no-manual shows no manual... */ @@ -2164,10 +2176,24 @@ static ParameterError opt_bool(struct OperationConfig *config, return PARAM_OK; } +static ParameterError existingfile(char **store, + const struct LongShort *a, + const char *filename) +{ + struct_stat info; + if(curlx_stat(filename, &info)) { + errorf("The file '%s' provided to --%s does not exist", + filename, a->lname); + return PARAM_BAD_USE; + } + return getstr(store, filename, DENY_BLANK); +} + /* opt_file handles file options */ static ParameterError opt_file(struct OperationConfig *config, const struct LongShort *a, - const char *nextarg) + const char *nextarg, + int max_recursive) { ParameterError err = PARAM_OK; if((nextarg[0] == '-') && nextarg[1]) { @@ -2180,22 +2206,26 @@ static ParameterError opt_file(struct OperationConfig *config, err = getstr(&config->unix_socket_path, nextarg, DENY_BLANK); break; case C_CACERT: /* --cacert */ - err = getstr(&config->cacert, nextarg, DENY_BLANK); + err = existingfile(&config->cacert, a, nextarg); break; case C_CAPATH: /* --capath */ err = getstr(&config->capath, nextarg, DENY_BLANK); break; case C_CERT: /* --cert */ - GetFileAndPassword(nextarg, &config->cert, &config->key_passwd); + err = GetFileAndPassword(nextarg, &config->cert, &config->key_passwd); break; case C_CONFIG: /* --config */ - if(parseconfig(nextarg)) { - errorf("cannot read config from '%s'", nextarg); - err = PARAM_READ_ERROR; + if(--max_recursive < 0) { + errorf("Max config file recursion level reached (%u)", + CONFIG_MAX_LEVELS); + err = PARAM_BAD_USE; + } + else { + err = parseconfig(nextarg, max_recursive, NULL); } break; case C_CRLFILE: /* --crlfile */ - err = getstr(&config->crlfile, nextarg, DENY_BLANK); + err = existingfile(&config->crlfile, a, nextarg); break; case C_DUMP_HEADER: /* --dump-header */ err = getstr(&config->headerfile, nextarg, DENY_BLANK); @@ -2220,26 +2250,26 @@ static ParameterError opt_file(struct OperationConfig *config, err = getstr(&config->key, nextarg, DENY_BLANK); break; case C_KNOWNHOSTS: /* --knownhosts */ - err = getstr(&config->knownhosts, nextarg, DENY_BLANK); + err = existingfile(&config->knownhosts, a, nextarg); break; case C_NETRC_FILE: /* --netrc-file */ - err = getstr(&config->netrc_file, nextarg, DENY_BLANK); + err = existingfile(&config->netrc_file, a, nextarg); break; case C_OUTPUT: /* --output */ err = parse_output(config, nextarg); break; case C_PROXY_CACERT: /* --proxy-cacert */ - err = getstr(&config->proxy_cacert, nextarg, DENY_BLANK); + err = existingfile(&config->proxy_cacert, a, nextarg); break; case C_PROXY_CAPATH: /* --proxy-capath */ err = getstr(&config->proxy_capath, nextarg, DENY_BLANK); break; case C_PROXY_CERT: /* --proxy-cert */ - GetFileAndPassword(nextarg, &config->proxy_cert, - &config->proxy_key_passwd); + err = GetFileAndPassword(nextarg, &config->proxy_cert, + &config->proxy_key_passwd); break; case C_PROXY_CRLFILE: /* --proxy-crlfile */ - err = getstr(&config->proxy_crlfile, nextarg, DENY_BLANK); + err = existingfile(&config->proxy_crlfile, a, nextarg); break; case C_PROXY_KEY: /* --proxy-key */ err = getstr(&config->proxy_key, nextarg, ALLOW_BLANK); @@ -2831,7 +2861,8 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ const char *nextarg, /* NULL if unset */ bool *usedarg, /* set to TRUE if the arg has been used */ - struct OperationConfig *config) + struct OperationConfig *config, + int max_recursive) { const char *parse = NULL; bool longopt = FALSE; @@ -2869,8 +2900,8 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ p = word; /* is there an '=' ? */ if(!curlx_str_until(&p, &out, MAX_OPTION_LEN, '=') && - !curlx_str_single(&p, '=') ) { - /* there's an equal sign */ + !curlx_str_single(&p, '=')) { + /* there is an equal sign */ char tempword[MAX_OPTION_LEN + 1]; memcpy(tempword, curlx_str(&out), curlx_strlen(&out)); tempword[curlx_strlen(&out)] = 0; @@ -2962,7 +2993,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ "Maybe ASCII was intended?", nextarg); } if(ARGTYPE(a->desc) == ARG_FILE) - err = opt_file(config, a, nextarg); + err = opt_file(config, a, nextarg, max_recursive); else /* if(ARGTYPE(a->desc) == ARG_STRG) */ err = opt_string(config, a, nextarg); if(a->desc & ARG_CLEAR) @@ -2986,7 +3017,7 @@ ParameterError getparameter(const char *flag, /* f or -long-flag */ error: if(nextalloc) - free(CURL_UNCONST(nextarg)); + curlx_free(CURL_UNCONST(nextarg)); return err; } @@ -3015,14 +3046,15 @@ ParameterError parse_args(int argc, argv_item_t argv[]) if(i < (argc - 1)) { nextarg = convert_tchar_to_UTF8(argv[i + 1]); if(!nextarg) { - unicodefree(orig_opt); + unicodefree(CURL_UNCONST(orig_opt)); return PARAM_NO_MEM; } } - result = getparameter(orig_opt, nextarg, &passarg, config); + result = getparameter(orig_opt, nextarg, &passarg, config, + CONFIG_MAX_LEVELS); - unicodefree(nextarg); + unicodefree(CURL_UNCONST(nextarg)); config = global->last; if(result == PARAM_NEXT_OPERATION) { /* Reset result as PARAM_NEXT_OPERATION is only used here and not @@ -3056,11 +3088,11 @@ ParameterError parse_args(int argc, argv_item_t argv[]) bool used; /* Just add the URL please */ - result = getparameter("--url", orig_opt, &used, config); + result = getparameter("--url", orig_opt, &used, config, 0); } if(!result) { - unicodefree(orig_opt); + unicodefree(CURL_UNCONST(orig_opt)); orig_opt = NULL; } } @@ -3083,6 +3115,6 @@ ParameterError parse_args(int argc, argv_item_t argv[]) helpf("%s", reason); } - unicodefree(orig_opt); + unicodefree(CURL_UNCONST(orig_opt)); return result; } diff --git a/src/tool_getparam.h b/src/tool_getparam.h index 6b97b9c11f45..44eb361edca5 100644 --- a/src/tool_getparam.h +++ b/src/tool_getparam.h @@ -319,12 +319,12 @@ typedef enum { #define ARG_FILE 3 /* requires an argument, usually a filename */ #define ARG_TYPEMASK 0x03 -#define ARGTYPE(x) ((x) & ARG_TYPEMASK) +#define ARGTYPE(x) ((x) & ARG_TYPEMASK) -#define ARG_DEPR 0x10 /* deprecated option */ +#define ARG_DEPR 0x10 /* deprecated option */ #define ARG_CLEAR 0x20 /* clear cmdline argument */ -#define ARG_TLS 0x40 /* requires TLS support */ -#define ARG_NO 0x80 /* set if the option is documented as --no-* */ +#define ARG_TLS 0x40 /* requires TLS support */ +#define ARG_NO 0x80 /* set if the option is documented as --no-* */ struct LongShort { const char *lname; /* long name option */ @@ -335,7 +335,6 @@ struct LongShort { typedef enum { PARAM_OK = 0, - PARAM_OPTION_AMBIGUOUS, PARAM_OPTION_UNKNOWN, PARAM_REQUIRES_PARAMETER, PARAM_BAD_USE, @@ -358,6 +357,7 @@ typedef enum { PARAM_EXPAND_ERROR, /* --expand problem */ PARAM_BLANK_STRING, PARAM_VAR_SYNTAX, /* --variable syntax error */ + PARAM_RECURSION, PARAM_LAST } ParameterError; @@ -368,27 +368,28 @@ const struct LongShort *findshortopt(char letter); ParameterError getparameter(const char *flag, const char *nextarg, bool *usedarg, - struct OperationConfig *config); + struct OperationConfig *config, + int max_recursive); #ifdef UNITTESTS -void parse_cert_parameter(const char *cert_parameter, - char **certname, - char **passphrase); +ParameterError parse_cert_parameter(const char *cert_parameter, + char **certname, + char **passphrase); #endif ParameterError parse_args(int argc, argv_item_t argv[]); -#if defined(UNICODE) && defined(_WIN32) && !defined(UNDER_CE) +#if defined(UNICODE) && defined(_WIN32) -#define convert_UTF8_to_tchar(ptr) curlx_convert_UTF8_to_wchar((ptr)) -#define convert_tchar_to_UTF8(ptr) curlx_convert_wchar_to_UTF8((ptr)) -#define unicodefree(ptr) curlx_unicodefree(ptr) +#define convert_UTF8_to_tchar(ptr) curlx_convert_UTF8_to_wchar(ptr) +#define convert_tchar_to_UTF8(ptr) curlx_convert_wchar_to_UTF8(ptr) +#define unicodefree(ptr) curlx_free(ptr) #else #define convert_UTF8_to_tchar(ptr) (const char *)(ptr) #define convert_tchar_to_UTF8(ptr) (const char *)(ptr) -#define unicodefree(ptr) do {} while(0) +#define unicodefree(ptr) do {} while(0) #endif diff --git a/src/tool_getpass.c b/src/tool_getpass.c index a92fb7594c78..f2423790fe2a 100644 --- a/src/tool_getpass.c +++ b/src/tool_getpass.c @@ -42,7 +42,7 @@ # include iodef #endif -#if defined(_WIN32) && !defined(UNDER_CE) +#ifdef _WIN32 # include #endif @@ -51,8 +51,6 @@ #endif #include "tool_getpass.h" -#include "memdebug.h" /* keep this as LAST include */ - #ifdef __VMS /* VMS implementation */ char *getpass_r(const char *prompt, char *buffer, size_t buflen) @@ -60,15 +58,12 @@ char *getpass_r(const char *prompt, char *buffer, size_t buflen) long sts; short chan; - /* MSK, 23-JAN-2004, iosbdef.h was not in VAX V7.2 or CC 6.4 */ - /* distribution so I created this. May revert back later to */ - /* struct _iosb iosb; */ - struct _iosb - { - short int iosb$w_status; /* status */ - short int iosb$w_bcnt; /* byte count */ - int unused; /* unused */ - } iosb; + /* iosbdef.h was not in VAX V7.2 or CC 6.4 */ + struct _isb { + short int iosb$w_status; /* status */ + short int iosb$w_bcnt; /* byte count */ + int unused; /* unused */ + } iosb; $DESCRIPTOR(ttdesc, "TT"); @@ -103,22 +98,21 @@ char *getpass_r(const char *prompt, char *buffer, size_t buflen) buffer[i] = '\0'; break; } - else - if(buffer[i] == '\b') - /* remove this letter and if this is not the first key, remove the + else if(buffer[i] == '\b') + /* remove this letter and if this is not the first key, remove the previous one as well */ - i = i - (i >= 1 ? 2 : 1); + i = i - (i >= 1 ? 2 : 1); } /* since echo is disabled, print a newline */ fputs("\n", tool_stderr); /* if user did not hit ENTER, terminate buffer */ if(i == buflen) - buffer[buflen-1] = '\0'; + buffer[buflen - 1] = '\0'; return buffer; /* we always return success */ } #define DONE -#endif /* _WIN32 && !UNDER_CE */ +#endif /* _WIN32 */ #ifndef DONE /* not previously provided */ diff --git a/src/tool_help.c b/src/tool_help.c index 7a3a4a3bf430..7355d2a7822f 100644 --- a/src/tool_help.c +++ b/src/tool_help.c @@ -33,8 +33,6 @@ #include "tool_cfgable.h" #include "terminal.h" -#include "memdebug.h" /* keep this as LAST include */ - struct category_descriptors { const char *opt; const char *desc; @@ -43,31 +41,31 @@ struct category_descriptors { static const struct category_descriptors categories[] = { /* important is left out because it is the default help page */ - {"auth", "Authentication methods", CURLHELP_AUTH}, - {"connection", "Manage connections", CURLHELP_CONNECTION}, - {"curl", "The command line tool itself", CURLHELP_CURL}, - {"deprecated", "Legacy", CURLHELP_DEPRECATED}, - {"dns", "Names and resolving", CURLHELP_DNS}, - {"file", "FILE protocol", CURLHELP_FILE}, - {"ftp", "FTP protocol", CURLHELP_FTP}, - {"global", "Global options", CURLHELP_GLOBAL}, - {"http", "HTTP and HTTPS protocol", CURLHELP_HTTP}, - {"imap", "IMAP protocol", CURLHELP_IMAP}, - {"ldap", "LDAP protocol", CURLHELP_LDAP}, - {"output", "File system output", CURLHELP_OUTPUT}, - {"pop3", "POP3 protocol", CURLHELP_POP3}, - {"post", "HTTP POST specific", CURLHELP_POST}, - {"proxy", "Options for proxies", CURLHELP_PROXY}, - {"scp", "SCP protocol", CURLHELP_SCP}, - {"sftp", "SFTP protocol", CURLHELP_SFTP}, - {"smtp", "SMTP protocol", CURLHELP_SMTP}, - {"ssh", "SSH protocol", CURLHELP_SSH}, - {"telnet", "TELNET protocol", CURLHELP_TELNET}, - {"tftp", "TFTP protocol", CURLHELP_TFTP}, - {"timeout", "Timeouts and delays", CURLHELP_TIMEOUT}, - {"tls", "TLS/SSL related", CURLHELP_TLS}, - {"upload", "Upload, sending data", CURLHELP_UPLOAD}, - {"verbose", "Tracing, logging etc", CURLHELP_VERBOSE} + { "auth", "Authentication methods", CURLHELP_AUTH }, + { "connection", "Manage connections", CURLHELP_CONNECTION }, + { "curl", "The command line tool itself", CURLHELP_CURL }, + { "deprecated", "Legacy", CURLHELP_DEPRECATED }, + { "dns", "Names and resolving", CURLHELP_DNS }, + { "file", "FILE protocol", CURLHELP_FILE }, + { "ftp", "FTP protocol", CURLHELP_FTP }, + { "global", "Global options", CURLHELP_GLOBAL }, + { "http", "HTTP and HTTPS protocol", CURLHELP_HTTP }, + { "imap", "IMAP protocol", CURLHELP_IMAP }, + { "ldap", "LDAP protocol", CURLHELP_LDAP }, + { "output", "File system output", CURLHELP_OUTPUT }, + { "pop3", "POP3 protocol", CURLHELP_POP3 }, + { "post", "HTTP POST specific", CURLHELP_POST }, + { "proxy", "Options for proxies", CURLHELP_PROXY }, + { "scp", "SCP protocol", CURLHELP_SCP }, + { "sftp", "SFTP protocol", CURLHELP_SFTP }, + { "smtp", "SMTP protocol", CURLHELP_SMTP }, + { "ssh", "SSH protocol", CURLHELP_SSH }, + { "telnet", "TELNET protocol", CURLHELP_TELNET }, + { "tftp", "TFTP protocol", CURLHELP_TFTP }, + { "timeout", "Timeouts and delays", CURLHELP_TIMEOUT }, + { "tls", "TLS/SSL related", CURLHELP_TLS }, + { "upload", "Upload, sending data", CURLHELP_UPLOAD }, + { "verbose", "Tracing, logging etc", CURLHELP_VERBOSE } }; static void print_category(unsigned int category, unsigned int cols) @@ -87,14 +85,18 @@ static void print_category(unsigned int category, unsigned int cols) if(len > longdesc) longdesc = len; } - if(longopt + longdesc > cols) + + if(longdesc > cols) + longopt = 0; /* avoid wrap-around */ + else if(longopt + longdesc > cols) longopt = cols - longdesc; for(i = 0; helptext[i].opt; ++i) if(helptext[i].categories & category) { size_t opt = longopt; size_t desclen = strlen(helptext[i].desc); - if(opt + desclen >= (cols - 2)) { + /* avoid wrap-around */ + if(cols >= 2 && opt + desclen >= (cols - 2)) { if(desclen < (cols - 2)) opt = (cols - 3) - desclen; else @@ -226,7 +228,8 @@ void tool_help(const char *category) unsigned int cols = get_terminal_columns(); /* If no category was provided */ if(!category) { - const char *category_note = "\nThis is not the full help; this " + const char *category_note = + "\nThis is not the full help; this " "menu is split into categories.\nUse \"--help category\" to get " "an overview of all categories, which are:"; const char *category_note2 = @@ -301,7 +304,7 @@ void tool_help(const char *category) static bool is_debug(void) { - const char *const *builtin; + const char * const *builtin; for(builtin = feature_names; *builtin; ++builtin) if(curl_strequal("debug", *builtin)) return TRUE; @@ -310,7 +313,7 @@ static bool is_debug(void) void tool_version_info(void) { - const char *const *builtin; + const char * const *builtin; if(is_debug()) curl_mfprintf(tool_stderr, "WARNING: this libcurl is Debug-enabled, " "do not use in production\n\n"); @@ -360,7 +363,7 @@ void tool_version_info(void) #ifdef CURL_CA_EMBED ++feat_ext_count; #endif - feat_ext = malloc(sizeof(*feature_names) * (feat_ext_count + 1)); + feat_ext = curlx_malloc(sizeof(*feature_names) * (feat_ext_count + 1)); if(feat_ext) { memcpy((void *)feat_ext, feature_names, sizeof(*feature_names) * feature_count); @@ -375,7 +378,7 @@ void tool_version_info(void) for(builtin = feat_ext; *builtin; ++builtin) curl_mprintf(" %s", *builtin); puts(""); /* newline */ - free((void *)feat_ext); + curlx_free((void *)feat_ext); } } if(strcmp(CURL_VERSION, curlinfo->version)) { diff --git a/src/tool_helpers.c b/src/tool_helpers.c index fbf3f1c932e0..c32e1bbaabe1 100644 --- a/src/tool_helpers.c +++ b/src/tool_helpers.c @@ -27,7 +27,6 @@ #include "tool_msgs.h" #include "tool_getparam.h" #include "tool_helpers.h" -#include "memdebug.h" /* keep this as LAST include */ /* ** Helper functions that are used from more than one source file. @@ -40,8 +39,6 @@ const char *param2text(ParameterError error) return "had unsupported trailing garbage"; case PARAM_OPTION_UNKNOWN: return "is unknown"; - case PARAM_OPTION_AMBIGUOUS: - return "is ambiguous"; case PARAM_REQUIRES_PARAMETER: return "requires parameter"; case PARAM_BAD_USE: @@ -78,7 +75,7 @@ const char *param2text(ParameterError error) int SetHTTPrequest(HttpReq req, HttpReq *store) { /* this mirrors the HttpReq enum in tool_sdecls.h */ - const char *reqname[]= { + const char *reqname[] = { "", /* unspec */ "GET (-G, --get)", "HEAD (-I, --head)", @@ -102,7 +99,7 @@ int SetHTTPrequest(HttpReq req, HttpReq *store) void customrequest_helper(HttpReq req, char *method) { /* this mirrors the HttpReq enum in tool_sdecls.h */ - const char *dflt[]= { + const char *dflt[] = { "GET", "GET", "HEAD", diff --git a/src/tool_ipfs.c b/src/tool_ipfs.c index 13124133eaf3..25bff3152f7c 100644 --- a/src/tool_ipfs.c +++ b/src/tool_ipfs.c @@ -28,102 +28,71 @@ #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) +/* input string ends in slash? */ +static bool has_trailing_slash(const char *input) { - if(*input && **input) { - size_t len = strlen(*input); - if(((*input)[len - 1] != '/')) { - struct dynbuf dyn; - curlx_dyn_init(&dyn, len + 2); - - if(curlx_dyn_addn(&dyn, *input, len)) { - tool_safefree(*input); - return CURLE_OUT_OF_MEMORY; - } - - tool_safefree(*input); - - if(curlx_dyn_addn(&dyn, "/", 1)) - return CURLE_OUT_OF_MEMORY; - - *input = curlx_dyn_ptr(&dyn); - } - } - - return CURLE_OK; + size_t len = strlen(input); + return (len && input[len - 1] == '/'); } static char *ipfs_gateway(void) { - char *ipfs_path = NULL; - char *gateway_composed_file_path = NULL; - FILE *gateway_file = NULL; - char *gateway = curl_getenv("IPFS_GATEWAY"); + char *ipfs_path_c = NULL; + char *gateway_composed_c = NULL; + FILE *gfile = NULL; + char *gateway_env = getenv("IPFS_GATEWAY"); - /* Gateway is found from environment variable. */ - if(gateway) { - if(ensure_trailing_slash(&gateway)) - goto fail; - return gateway; - } + if(gateway_env) + return curlx_strdup(gateway_env); /* Try to find the gateway in the IPFS data folder. */ - ipfs_path = curl_getenv("IPFS_PATH"); + ipfs_path_c = curl_getenv("IPFS_PATH"); - if(!ipfs_path) { + if(!ipfs_path_c) { char *home = getenv("HOME"); - if(home && *home) - ipfs_path = curl_maprintf("%s/.ipfs/", home); /* fallback to "~/.ipfs", as that is the default location. */ + if(home && *home) + ipfs_path_c = curl_maprintf("%s/.ipfs/", home); + if(!ipfs_path_c) + goto fail; } - if(!ipfs_path || ensure_trailing_slash(&ipfs_path)) - goto fail; - - gateway_composed_file_path = curl_maprintf("%sgateway", ipfs_path); + gateway_composed_c = + curl_maprintf("%s%sgateway", ipfs_path_c, + has_trailing_slash(ipfs_path_c) ? "" : "/"); - if(!gateway_composed_file_path) + if(!gateway_composed_c) goto fail; - gateway_file = curlx_fopen(gateway_composed_file_path, FOPEN_READTEXT); - tool_safefree(gateway_composed_file_path); + gfile = curlx_fopen(gateway_composed_c, FOPEN_READTEXT); + curl_free(gateway_composed_c); - if(gateway_file) { + if(gfile) { int c; struct dynbuf dyn; + char *gateway = NULL; 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') { + while((c = getc(gfile)) != EOF && c != '\n' && c != '\r') { char c_char = (char)c; if(curlx_dyn_addn(&dyn, &c_char, 1)) goto fail; } - curlx_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; - - tool_safefree(ipfs_path); + curl_free(ipfs_path_c); + curlx_fclose(gfile); return gateway; } fail: - if(gateway_file) - curlx_fclose(gateway_file); - tool_safefree(gateway); - tool_safefree(ipfs_path); + if(gfile) + curlx_fclose(gfile); + curl_free(ipfs_path_c); return NULL; } @@ -161,20 +130,13 @@ CURLcode ipfs_url_rewrite(CURLU *uh, const char *protocol, char **url, * if we do have something but if it is 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); + CURLU_GUESS_SCHEME)) { + gateway = curlx_strdup(config->ipfs_gateway); if(!gateway) { result = CURLE_URL_MALFORMAT; goto clean; } - } else { result = CURLE_BAD_FUNCTION_ARGUMENT; @@ -182,7 +144,6 @@ CURLcode ipfs_url_rewrite(CURLU *uh, const char *protocol, char **url, } } else { - /* this is ensured to end in a trailing / within ipfs_gateway() */ gateway = ipfs_gateway(); if(!gateway) { result = CURLE_FILE_COULDNT_READ_FILE; @@ -196,31 +157,25 @@ CURLcode ipfs_url_rewrite(CURLU *uh, const char *protocol, char **url, } /* check for unsupported gateway parts */ - if(curl_url_get(gatewayurl, CURLUPART_QUERY, &gwquery, 0) - != CURLUE_NO_QUERY) { + 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)) { + if(curl_url_get(gatewayurl, CURLUPART_HOST, &gwhost, CURLU_URLDECODE) || + curl_url_get(gatewayurl, CURLUPART_SCHEME, &gwscheme, CURLU_URLDECODE) || + curl_url_get(gatewayurl, CURLUPART_PORT, &gwport, CURLU_URLDECODE) || + curl_url_get(gatewayurl, CURLUPART_PATH, &gwpath, 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); + if(curl_url_get(uh, CURLUPART_PATH, &inputpath, CURLU_URLDECODE)) + goto clean; /* inputpath might be NULL or a valid pointer now */ - /* set gateway parts in input url */ + /* 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)) @@ -230,18 +185,13 @@ CURLcode ipfs_url_rewrite(CURLU *uh, const char *protocol, char **url, if(inputpath && (inputpath[0] == '/') && !inputpath[1]) *inputpath = '\0'; - /* ensure the gateway path ends with a trailing slash */ - ensure_trailing_slash(&gwpath); - - pathbuffer = curl_maprintf("%s%s/%s%s", gwpath, protocol, cid, + pathbuffer = curl_maprintf("%s%s%s/%s%s", gwpath, + has_trailing_slash(gwpath) ? "" : "/", + protocol, cid, inputpath ? inputpath : ""); - if(!pathbuffer) { + if(!pathbuffer || + curl_url_set(uh, CURLUPART_PATH, pathbuffer, CURLU_URLENCODE)) goto clean; - } - - if(curl_url_set(uh, CURLUPART_PATH, pathbuffer, CURLU_URLENCODE)) { - goto clean; - } /* Free whatever it has now, rewriting is next */ tool_safefree(*url); @@ -249,8 +199,8 @@ CURLcode ipfs_url_rewrite(CURLU *uh, const char *protocol, char **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); + /* we need to strdup the URL so that we can call curlx_free() on it later */ + *url = curlx_strdup(cloneurl); curl_free(cloneurl); if(!*url) goto clean; @@ -258,7 +208,7 @@ CURLcode ipfs_url_rewrite(CURLU *uh, const char *protocol, char **url, result = CURLE_OK; clean: - free(gateway); + curlx_free(gateway); curl_free(gwhost); curl_free(gwpath); curl_free(gwquery); diff --git a/src/tool_libinfo.c b/src/tool_libinfo.c index d755532652c8..4ce22bd2273b 100644 --- a/src/tool_libinfo.c +++ b/src/tool_libinfo.c @@ -24,7 +24,6 @@ #include "tool_setup.h" #include "tool_libinfo.h" -#include "memdebug.h" /* keep this as LAST include */ /* global variable definitions, for libcurl runtime info */ @@ -62,7 +61,7 @@ static struct proto_name_tokenp { { "scp", &proto_scp }, { "sftp", &proto_sftp }, { "tftp", &proto_tftp }, - { NULL, NULL } + { NULL, NULL } }; bool feature_altsvc = FALSE; @@ -88,38 +87,38 @@ static struct feature_name_presentp { int feature_bitmask; } const maybe_feature[] = { /* Keep alphabetically sorted. */ - {"alt-svc", &feature_altsvc, CURL_VERSION_ALTSVC}, - {"AsynchDNS", NULL, CURL_VERSION_ASYNCHDNS}, - {"brotli", &feature_brotli, CURL_VERSION_BROTLI}, - {"CharConv", NULL, CURL_VERSION_CONV}, - {"Debug", NULL, CURL_VERSION_DEBUG}, - {"ECH", &feature_ech, 0}, - {"gsasl", NULL, CURL_VERSION_GSASL}, - {"GSS-API", NULL, CURL_VERSION_GSSAPI}, - {"HSTS", &feature_hsts, CURL_VERSION_HSTS}, - {"HTTP2", &feature_http2, CURL_VERSION_HTTP2}, - {"HTTP3", &feature_http3, CURL_VERSION_HTTP3}, - {"HTTPS-proxy", &feature_httpsproxy, CURL_VERSION_HTTPS_PROXY}, - {"IDN", NULL, CURL_VERSION_IDN}, - {"IPv6", NULL, CURL_VERSION_IPV6}, - {"Kerberos", NULL, CURL_VERSION_KERBEROS5}, - {"Largefile", NULL, CURL_VERSION_LARGEFILE}, - {"libz", &feature_libz, CURL_VERSION_LIBZ}, - {"MultiSSL", NULL, CURL_VERSION_MULTI_SSL}, - {"NTLM", &feature_ntlm, CURL_VERSION_NTLM}, - {"NTLM_WB", &feature_ntlm_wb, CURL_VERSION_NTLM_WB}, - {"PSL", NULL, CURL_VERSION_PSL}, - {"SPNEGO", &feature_spnego, CURL_VERSION_SPNEGO}, - {"SSL", &feature_ssl, CURL_VERSION_SSL}, - {"SSPI", NULL, CURL_VERSION_SSPI}, - {"SSLS-EXPORT", &feature_ssls_export, 0}, - {"threadsafe", NULL, CURL_VERSION_THREADSAFE}, - {"TLS-SRP", &feature_tls_srp, CURL_VERSION_TLSAUTH_SRP}, - {"TrackMemory", NULL, CURL_VERSION_CURLDEBUG}, - {"Unicode", NULL, CURL_VERSION_UNICODE}, - {"UnixSockets", NULL, CURL_VERSION_UNIX_SOCKETS}, - {"zstd", &feature_zstd, CURL_VERSION_ZSTD}, - {NULL, NULL, 0} + { "alt-svc", &feature_altsvc, CURL_VERSION_ALTSVC }, + { "AsynchDNS", NULL, CURL_VERSION_ASYNCHDNS }, + { "brotli", &feature_brotli, CURL_VERSION_BROTLI }, + { "CharConv", NULL, CURL_VERSION_CONV }, + { "Debug", NULL, CURL_VERSION_DEBUG }, + { "ECH", &feature_ech, 0 }, + { "gsasl", NULL, CURL_VERSION_GSASL }, + { "GSS-API", NULL, CURL_VERSION_GSSAPI }, + { "HSTS", &feature_hsts, CURL_VERSION_HSTS }, + { "HTTP2", &feature_http2, CURL_VERSION_HTTP2 }, + { "HTTP3", &feature_http3, CURL_VERSION_HTTP3 }, + { "HTTPS-proxy", &feature_httpsproxy, CURL_VERSION_HTTPS_PROXY }, + { "IDN", NULL, CURL_VERSION_IDN }, + { "IPv6", NULL, CURL_VERSION_IPV6 }, + { "Kerberos", NULL, CURL_VERSION_KERBEROS5 }, + { "Largefile", NULL, CURL_VERSION_LARGEFILE }, + { "libz", &feature_libz, CURL_VERSION_LIBZ }, + { "MultiSSL", NULL, CURL_VERSION_MULTI_SSL }, + { "NTLM", &feature_ntlm, CURL_VERSION_NTLM }, + { "NTLM_WB", &feature_ntlm_wb, CURL_VERSION_NTLM_WB }, + { "PSL", NULL, CURL_VERSION_PSL }, + { "SPNEGO", &feature_spnego, CURL_VERSION_SPNEGO }, + { "SSL", &feature_ssl, CURL_VERSION_SSL }, + { "SSPI", NULL, CURL_VERSION_SSPI }, + { "SSLS-EXPORT", &feature_ssls_export, 0 }, + { "threadsafe", NULL, CURL_VERSION_THREADSAFE }, + { "TLS-SRP", &feature_tls_srp, CURL_VERSION_TLSAUTH_SRP }, + { "TrackMemory", NULL, CURL_VERSION_CURLDEBUG }, + { "Unicode", NULL, CURL_VERSION_UNICODE }, + { "UnixSockets", NULL, CURL_VERSION_UNIX_SOCKETS }, + { "zstd", &feature_zstd, CURL_VERSION_ZSTD }, + { NULL, NULL, 0 } }; static const char *fnames[CURL_ARRAYSIZE(maybe_feature)]; @@ -138,7 +137,7 @@ size_t feature_count; CURLcode get_libcurl_info(void) { CURLcode result = CURLE_OK; - const char *const *builtin; + const char * const *builtin; /* Pointer to libcurl's runtime version information */ curlinfo = curl_version_info(CURLVERSION_NOW); @@ -187,7 +186,7 @@ CURLcode get_libcurl_info(void) } feature_libssh2 = curlinfo->libssh_version && - !strncmp("libssh2", curlinfo->libssh_version, 7); + !strncmp("libssh2", curlinfo->libssh_version, 7); return CURLE_OK; } diff --git a/src/tool_libinfo.h b/src/tool_libinfo.h index 5e6e1de24c43..ddc41a133867 100644 --- a/src/tool_libinfo.h +++ b/src/tool_libinfo.h @@ -27,7 +27,6 @@ /* global variable declarations, for libcurl runtime info */ - extern curl_version_info_data *curlinfo; extern const char * const *built_in_protos; diff --git a/src/tool_listhelp.c b/src/tool_listhelp.c index 21019c7de161..48a32214b801 100644 --- a/src/tool_listhelp.c +++ b/src/tool_listhelp.c @@ -33,831 +33,831 @@ */ const struct helptxt helptext[] = { - {" --abstract-unix-socket ", - "Connect via abstract Unix domain socket", - CURLHELP_CONNECTION}, - {" --alt-svc ", - "Enable alt-svc with this cache file", - CURLHELP_HTTP}, - {" --anyauth", - "Pick any authentication method", - CURLHELP_HTTP | CURLHELP_PROXY | CURLHELP_AUTH}, - {"-a, --append", - "Append to target file when uploading", - CURLHELP_FTP | CURLHELP_SFTP}, - {" --aws-sigv4 ", - "AWS V4 signature auth", - CURLHELP_AUTH | CURLHELP_HTTP}, - {" --basic", - "HTTP Basic Authentication", - CURLHELP_AUTH}, - {" --ca-native", - "Load CA certs from the OS", - CURLHELP_TLS}, - {" --cacert ", - "CA certificate to verify peer against", - CURLHELP_TLS}, - {" --capath ", - "CA directory to verify peer against", - CURLHELP_TLS}, - {"-E, --cert ", - "Client certificate file and password", - CURLHELP_TLS}, - {" --cert-status", - "Verify server cert status OCSP-staple", - CURLHELP_TLS}, - {" --cert-type ", - "Certificate type (DER/PEM/ENG/PROV/P12)", - CURLHELP_TLS}, - {" --ciphers ", - "TLS 1.2 (1.1, 1.0) ciphers to use", - CURLHELP_TLS}, - {" --compressed", - "Request compressed response", - CURLHELP_HTTP}, - {" --compressed-ssh", - "Enable SSH compression", - CURLHELP_SCP | CURLHELP_SSH}, - {"-K, --config ", - "Read config from a file", - CURLHELP_CURL}, - {" --connect-timeout ", - "Maximum time allowed to connect", - CURLHELP_CONNECTION | CURLHELP_TIMEOUT}, - {" --connect-to ", - "Connect to host2 instead of host1", - CURLHELP_CONNECTION | CURLHELP_DNS}, - {"-C, --continue-at ", - "Resumed transfer offset", - CURLHELP_CONNECTION}, - {"-b, --cookie ", - "Send cookies from string/load from file", - CURLHELP_HTTP}, - {"-c, --cookie-jar ", - "Save cookies to after operation", - CURLHELP_HTTP}, - {" --create-dirs", - "Create necessary local directory hierarchy", - CURLHELP_OUTPUT}, - {" --create-file-mode ", - "File mode for created files", - CURLHELP_SFTP | CURLHELP_SCP | CURLHELP_FILE | CURLHELP_UPLOAD}, - {" --crlf", - "Convert LF to CRLF in upload", - CURLHELP_FTP | CURLHELP_SMTP}, - {" --crlfile ", - "Certificate Revocation list", - CURLHELP_TLS}, - {" --curves ", - "(EC) TLS key exchange algorithms to request", - CURLHELP_TLS}, - {"-d, --data ", - "HTTP POST data", - CURLHELP_IMPORTANT | CURLHELP_HTTP | CURLHELP_POST | CURLHELP_UPLOAD}, - {" --data-ascii ", - "HTTP POST ASCII data", - CURLHELP_HTTP | CURLHELP_POST | CURLHELP_UPLOAD}, - {" --data-binary ", - "HTTP POST binary data", - CURLHELP_HTTP | CURLHELP_POST | CURLHELP_UPLOAD}, - {" --data-raw ", - "HTTP POST data, '@' allowed", - CURLHELP_HTTP | CURLHELP_POST | CURLHELP_UPLOAD}, - {" --data-urlencode ", - "HTTP POST data URL encoded", - CURLHELP_HTTP | CURLHELP_POST | CURLHELP_UPLOAD}, - {" --delegation ", - "GSS-API delegation permission", - CURLHELP_AUTH}, - {" --digest", - "HTTP Digest Authentication", - CURLHELP_PROXY | CURLHELP_AUTH | CURLHELP_HTTP}, - {"-q, --disable", - "Disable .curlrc", - CURLHELP_CURL}, - {" --disable-eprt", - "Inhibit using EPRT or LPRT", - CURLHELP_FTP}, - {" --disable-epsv", - "Inhibit using EPSV", - CURLHELP_FTP}, - {" --disallow-username-in-url", - "Disallow username in URL", - CURLHELP_CURL}, - {" --dns-interface ", - "Interface to use for DNS requests", - CURLHELP_DNS}, - {" --dns-ipv4-addr
", - "IPv4 address to use for DNS requests", - CURLHELP_DNS}, - {" --dns-ipv6-addr
", - "IPv6 address to use for DNS requests", - CURLHELP_DNS}, - {" --dns-servers ", - "DNS server addrs to use", - CURLHELP_DNS}, - {" --doh-cert-status", - "Verify DoH server cert status OCSP-staple", - CURLHELP_DNS | CURLHELP_TLS}, - {" --doh-insecure", - "Allow insecure DoH server connections", - CURLHELP_DNS | CURLHELP_TLS}, - {" --doh-url ", - "Resolve hostnames over DoH", - CURLHELP_DNS}, - {" --dump-ca-embed", - "Write the embedded CA bundle to standard output", - CURLHELP_HTTP | CURLHELP_PROXY | CURLHELP_TLS}, - {"-D, --dump-header ", - "Write the received headers to ", - CURLHELP_HTTP | CURLHELP_FTP}, - {" --ech ", - "Configure ECH", - CURLHELP_TLS}, - {" --egd-file ", - "EGD socket path for random data", - CURLHELP_DEPRECATED}, - {" --engine ", - "Crypto engine to use", - CURLHELP_TLS}, - {" --etag-compare ", - "Load ETag from file", - CURLHELP_HTTP}, - {" --etag-save ", - "Parse incoming ETag and save to a file", - CURLHELP_HTTP}, - {" --expect100-timeout ", - "How long to wait for 100-continue", - CURLHELP_HTTP | CURLHELP_TIMEOUT}, - {"-f, --fail", - "Fail fast with no output on HTTP errors", - CURLHELP_IMPORTANT | CURLHELP_HTTP}, - {" --fail-early", - "Fail on first transfer error", - CURLHELP_CURL | CURLHELP_GLOBAL}, - {" --fail-with-body", - "Fail on HTTP errors but save the body", - CURLHELP_HTTP | CURLHELP_OUTPUT}, - {" --false-start", - "Enable TLS False Start", - CURLHELP_DEPRECATED}, - {" --follow", - "Follow redirects per spec", - CURLHELP_HTTP}, - {"-F, --form ", - "Specify multipart MIME data", - CURLHELP_HTTP | CURLHELP_UPLOAD | CURLHELP_POST | CURLHELP_IMAP | - CURLHELP_SMTP}, - {" --form-escape", - "Escape form fields using backslash", - CURLHELP_HTTP | CURLHELP_UPLOAD | CURLHELP_POST}, - {" --form-string ", - "Specify multipart MIME data", - CURLHELP_HTTP | CURLHELP_UPLOAD | CURLHELP_POST | CURLHELP_SMTP | - CURLHELP_IMAP}, - {" --ftp-account ", - "Account data string", - CURLHELP_FTP | CURLHELP_AUTH}, - {" --ftp-alternative-to-user ", - "String to replace USER [name]", - CURLHELP_FTP}, - {" --ftp-create-dirs", - "Create the remote dirs if not present", - CURLHELP_FTP | CURLHELP_SFTP}, - {" --ftp-method ", - "Control CWD usage", - CURLHELP_FTP}, - {" --ftp-pasv", - "Send PASV/EPSV instead of PORT", - CURLHELP_FTP}, - {"-P, --ftp-port
", - "Send PORT instead of PASV", - CURLHELP_FTP}, - {" --ftp-pret", - "Send PRET before PASV", - CURLHELP_FTP}, - {" --ftp-skip-pasv-ip", - "Skip the IP address for PASV", - CURLHELP_FTP}, - {" --ftp-ssl-ccc", - "Send CCC after authenticating", - CURLHELP_FTP | CURLHELP_TLS}, - {" --ftp-ssl-ccc-mode ", - "Set CCC mode", - CURLHELP_FTP | CURLHELP_TLS}, - {" --ftp-ssl-control", - "Require TLS for login, clear for transfer", - CURLHELP_FTP | CURLHELP_TLS}, - {"-G, --get", - "Put the post data in the URL and use GET", - CURLHELP_HTTP}, - {"-g, --globoff", - "Disable URL globbing with {} and []", - CURLHELP_CURL}, - {" --happy-eyeballs-timeout-ms ", - "Time for IPv6 before IPv4", - CURLHELP_CONNECTION | CURLHELP_TIMEOUT}, - {" --haproxy-clientip ", - "Set address in HAProxy PROXY", - CURLHELP_HTTP | CURLHELP_PROXY}, - {" --haproxy-protocol", - "Send HAProxy PROXY protocol v1 header", - CURLHELP_HTTP | CURLHELP_PROXY}, - {"-I, --head", - "Show document info only", - CURLHELP_HTTP | CURLHELP_FTP | CURLHELP_FILE}, - {"-H, --header
", - "Pass custom header(s) to server", - CURLHELP_HTTP | CURLHELP_IMAP | CURLHELP_SMTP}, - {"-h, --help ", - "Get help for commands", - CURLHELP_IMPORTANT | CURLHELP_CURL}, - {" --hostpubmd5 ", - "Acceptable MD5 hash of host public key", - CURLHELP_SFTP | CURLHELP_SCP | CURLHELP_SSH}, - {" --hostpubsha256 ", - "Acceptable SHA256 hash of host public key", - CURLHELP_SFTP | CURLHELP_SCP | CURLHELP_SSH}, - {" --hsts ", - "Enable HSTS with this cache file", - CURLHELP_HTTP}, - {" --http0.9", - "Allow HTTP/0.9 responses", - CURLHELP_HTTP}, - {"-0, --http1.0", - "Use HTTP/1.0", - CURLHELP_HTTP}, - {" --http1.1", - "Use HTTP/1.1", - CURLHELP_HTTP}, - {" --http2", - "Use HTTP/2", - CURLHELP_HTTP}, - {" --http2-prior-knowledge", - "Use HTTP/2 without HTTP/1.1 Upgrade", - CURLHELP_HTTP}, - {" --http3", - "Use HTTP/3", - CURLHELP_HTTP}, - {" --http3-only", - "Use HTTP/3 only", - CURLHELP_HTTP}, - {" --ignore-content-length", - "Ignore the size of the remote resource", - CURLHELP_HTTP | CURLHELP_FTP}, - {"-k, --insecure", - "Allow insecure server connections", - CURLHELP_TLS | CURLHELP_SFTP | CURLHELP_SCP | CURLHELP_SSH}, - {" --interface ", - "Use network interface", - CURLHELP_CONNECTION}, - {" --ip-tos ", - "Set IP Type of Service or Traffic Class", - CURLHELP_CONNECTION}, - {" --ipfs-gateway ", - "Gateway for IPFS", - CURLHELP_CURL}, - {"-4, --ipv4", - "Resolve names to IPv4 addresses", - CURLHELP_CONNECTION | CURLHELP_DNS}, - {"-6, --ipv6", - "Resolve names to IPv6 addresses", - CURLHELP_CONNECTION | CURLHELP_DNS}, - {" --json ", - "HTTP POST JSON", - CURLHELP_HTTP | CURLHELP_POST | CURLHELP_UPLOAD}, - {"-j, --junk-session-cookies", - "Ignore session cookies read from file", - CURLHELP_HTTP}, - {" --keepalive-cnt ", - "Maximum number of keepalive probes", - CURLHELP_CONNECTION}, - {" --keepalive-time ", - "Interval time for keepalive probes", - CURLHELP_CONNECTION | CURLHELP_TIMEOUT}, - {" --key ", - "Private key filename", - CURLHELP_TLS | CURLHELP_SSH}, - {" --key-type ", - "Private key file type (DER/PEM/ENG)", - CURLHELP_TLS}, - {" --knownhosts ", - "Specify knownhosts path", - CURLHELP_SSH}, - {" --krb ", - "Enable Kerberos with security ", - CURLHELP_DEPRECATED}, - {" --libcurl ", - "Generate libcurl code for this command line", - CURLHELP_CURL | CURLHELP_GLOBAL}, - {" --limit-rate ", - "Limit transfer speed to RATE", - CURLHELP_CONNECTION}, - {"-l, --list-only", - "List only mode", - CURLHELP_FTP | CURLHELP_POP3 | CURLHELP_SFTP | CURLHELP_FILE}, - {" --local-port ", - "Use a local port number within RANGE", - CURLHELP_CONNECTION}, - {"-L, --location", - "Follow redirects", - CURLHELP_HTTP}, - {" --location-trusted", - "As --location, but send secrets to other hosts", - CURLHELP_HTTP | CURLHELP_AUTH}, - {" --login-options ", - "Server login options", - CURLHELP_IMAP | CURLHELP_POP3 | CURLHELP_SMTP | CURLHELP_AUTH | - CURLHELP_LDAP}, - {" --mail-auth
", - "Originator address of the original email", - CURLHELP_SMTP}, - {" --mail-from
", - "Mail from this address", - CURLHELP_SMTP}, - {" --mail-rcpt
", - "Mail to this address", - CURLHELP_SMTP}, - {" --mail-rcpt-allowfails", - "Allow RCPT TO command to fail", - CURLHELP_SMTP}, - {"-M, --manual", - "Display the full manual", - CURLHELP_CURL}, - {" --max-filesize ", - "Maximum file size to download", - CURLHELP_CONNECTION}, - {" --max-redirs ", - "Maximum number of redirects allowed", - CURLHELP_HTTP}, - {"-m, --max-time ", - "Maximum time allowed for transfer", - CURLHELP_CONNECTION | CURLHELP_TIMEOUT}, - {" --metalink", - "Process given URLs as metalink XML file", - CURLHELP_DEPRECATED}, - {" --mptcp", - "Enable Multipath TCP", - CURLHELP_CONNECTION}, - {" --negotiate", - "Use HTTP Negotiate (SPNEGO) authentication", - CURLHELP_AUTH | CURLHELP_HTTP}, - {"-n, --netrc", - "Must read .netrc for username and password", - CURLHELP_AUTH}, - {" --netrc-file ", - "Specify FILE for netrc", - CURLHELP_AUTH}, - {" --netrc-optional", - "Use either .netrc or URL", - CURLHELP_AUTH}, - {"-:, --next", - "Make next URL use separate options", - CURLHELP_CURL}, - {" --no-alpn", - "Disable the ALPN TLS extension", - CURLHELP_TLS | CURLHELP_HTTP}, - {"-N, --no-buffer", - "Disable buffering of the output stream", - CURLHELP_OUTPUT}, - {" --no-clobber", - "Do not overwrite files that already exist", - CURLHELP_OUTPUT}, - {" --no-keepalive", - "Disable TCP keepalive on the connection", - CURLHELP_CONNECTION}, - {" --no-npn", - "Disable the NPN TLS extension", - CURLHELP_DEPRECATED}, - {" --no-progress-meter", - "Do not show the progress meter", - CURLHELP_VERBOSE}, - {" --no-sessionid", - "Disable SSL session-ID reusing", - CURLHELP_TLS}, - {" --noproxy ", - "List of hosts which do not use proxy", - CURLHELP_PROXY}, - {" --ntlm", - "HTTP NTLM authentication", - CURLHELP_AUTH | CURLHELP_HTTP}, - {" --ntlm-wb", - "HTTP NTLM authentication with winbind", - CURLHELP_DEPRECATED}, - {" --oauth2-bearer ", - "OAuth 2 Bearer Token", - CURLHELP_AUTH | CURLHELP_IMAP | CURLHELP_POP3 | CURLHELP_SMTP | - CURLHELP_LDAP}, - {" --out-null", - "Discard response data into the void", - CURLHELP_OUTPUT}, - {"-o, --output ", - "Write to file instead of stdout", - CURLHELP_IMPORTANT | CURLHELP_OUTPUT}, - {" --output-dir ", - "Directory to save files in", - CURLHELP_OUTPUT}, - {"-Z, --parallel", - "Perform transfers in parallel", - CURLHELP_CONNECTION | CURLHELP_CURL | CURLHELP_GLOBAL}, - {" --parallel-immediate", - "Do not wait for multiplexing", - CURLHELP_CONNECTION | CURLHELP_CURL | CURLHELP_GLOBAL}, - {" --parallel-max ", - "Maximum concurrency for parallel transfers", - CURLHELP_CONNECTION | CURLHELP_CURL | CURLHELP_GLOBAL}, - {" --parallel-max-host ", - "Maximum connections to a single host", - CURLHELP_CONNECTION | CURLHELP_CURL | CURLHELP_GLOBAL}, - {" --pass ", - "Passphrase for the private key", - CURLHELP_SSH | CURLHELP_TLS | CURLHELP_AUTH}, - {" --path-as-is", - "Do not squash .. sequences in URL path", - CURLHELP_CURL}, - {" --pinnedpubkey ", - "Public key to verify peer against", - CURLHELP_TLS}, - {" --post301", - "Do not switch to GET after a 301 redirect", - CURLHELP_HTTP | CURLHELP_POST}, - {" --post302", - "Do not switch to GET after a 302 redirect", - CURLHELP_HTTP | CURLHELP_POST}, - {" --post303", - "Do not switch to GET after a 303 redirect", - CURLHELP_HTTP | CURLHELP_POST}, - {" --preproxy <[protocol://]host[:port]>", - "Use this proxy first", - CURLHELP_PROXY}, - {"-#, --progress-bar", - "Display transfer progress as a bar", - CURLHELP_VERBOSE | CURLHELP_GLOBAL}, - {" --proto ", - "Enable/disable PROTOCOLS", - CURLHELP_CONNECTION | CURLHELP_CURL}, - {" --proto-default ", - "Use PROTOCOL for any URL missing a scheme", - CURLHELP_CONNECTION | CURLHELP_CURL}, - {" --proto-redir ", - "Enable/disable PROTOCOLS on redirect", - CURLHELP_CONNECTION | CURLHELP_CURL}, - {"-x, --proxy <[protocol://]host[:port]>", - "Use this proxy", - CURLHELP_PROXY}, - {" --proxy-anyauth", - "Pick any proxy authentication method", - CURLHELP_PROXY | CURLHELP_AUTH}, - {" --proxy-basic", - "Use Basic authentication on the proxy", - CURLHELP_PROXY | CURLHELP_AUTH}, - {" --proxy-ca-native", - "Load CA certs from the OS to verify proxy", - CURLHELP_TLS}, - {" --proxy-cacert ", - "CA certificates to verify proxy against", - CURLHELP_PROXY | CURLHELP_TLS}, - {" --proxy-capath ", - "CA directory to verify proxy against", - CURLHELP_PROXY | CURLHELP_TLS}, - {" --proxy-cert ", - "Set client certificate for proxy", - CURLHELP_PROXY | CURLHELP_TLS}, - {" --proxy-cert-type ", - "Client certificate type for HTTPS proxy", - CURLHELP_PROXY | CURLHELP_TLS}, - {" --proxy-ciphers ", - "TLS 1.2 (1.1, 1.0) ciphers to use for proxy", - CURLHELP_PROXY | CURLHELP_TLS}, - {" --proxy-crlfile ", - "Set a CRL list for proxy", - CURLHELP_PROXY | CURLHELP_TLS}, - {" --proxy-digest", - "Digest auth with the proxy", - CURLHELP_PROXY | CURLHELP_TLS}, - {" --proxy-header
", - "Pass custom header(s) to proxy", - CURLHELP_PROXY}, - {" --proxy-http2", - "Use HTTP/2 with HTTPS proxy", - CURLHELP_HTTP | CURLHELP_PROXY}, - {" --proxy-insecure", - "Skip HTTPS proxy cert verification", - CURLHELP_PROXY | CURLHELP_TLS}, - {" --proxy-key ", - "Private key for HTTPS proxy", - CURLHELP_PROXY | CURLHELP_TLS}, - {" --proxy-key-type ", - "Private key file type for proxy", - CURLHELP_PROXY | CURLHELP_TLS}, - {" --proxy-negotiate", - "HTTP Negotiate (SPNEGO) auth with the proxy", - CURLHELP_PROXY | CURLHELP_AUTH}, - {" --proxy-ntlm", - "NTLM authentication with the proxy", - CURLHELP_PROXY | CURLHELP_AUTH}, - {" --proxy-pass ", - "Passphrase for private key for HTTPS proxy", - CURLHELP_PROXY | CURLHELP_TLS | CURLHELP_AUTH}, - {" --proxy-pinnedpubkey ", - "FILE/HASHES public key to verify proxy with", - CURLHELP_PROXY | CURLHELP_TLS}, - {" --proxy-service-name ", - "SPNEGO proxy service name", - CURLHELP_PROXY | CURLHELP_TLS}, - {" --proxy-ssl-allow-beast", - "Allow this security flaw for HTTPS proxy", - CURLHELP_PROXY | CURLHELP_TLS}, - {" --proxy-ssl-auto-client-cert", - "Auto client certificate for proxy", - CURLHELP_PROXY | CURLHELP_TLS}, - {" --proxy-tls13-ciphers ", - "TLS 1.3 proxy cipher suites", - CURLHELP_PROXY | CURLHELP_TLS}, - {" --proxy-tlsauthtype ", - "TLS authentication type for HTTPS proxy", - CURLHELP_PROXY | CURLHELP_TLS | CURLHELP_AUTH}, - {" --proxy-tlspassword ", - "TLS password for HTTPS proxy", - CURLHELP_PROXY | CURLHELP_TLS | CURLHELP_AUTH}, - {" --proxy-tlsuser ", - "TLS username for HTTPS proxy", - CURLHELP_PROXY | CURLHELP_TLS | CURLHELP_AUTH}, - {" --proxy-tlsv1", - "TLSv1 for HTTPS proxy", - CURLHELP_PROXY | CURLHELP_TLS | CURLHELP_AUTH}, - {"-U, --proxy-user ", - "Proxy user and password", - CURLHELP_PROXY | CURLHELP_AUTH}, - {" --proxy1.0 ", - "Use HTTP/1.0 proxy on given port", - CURLHELP_PROXY}, - {"-p, --proxytunnel", - "HTTP proxy tunnel (using CONNECT)", - CURLHELP_PROXY}, - {" --pubkey ", - "SSH Public key filename", - CURLHELP_SFTP | CURLHELP_SCP | CURLHELP_SSH | CURLHELP_AUTH}, - {"-Q, --quote ", - "Send command(s) to server before transfer", - CURLHELP_FTP | CURLHELP_SFTP}, - {" --random-file ", - "File for reading random data from", - CURLHELP_DEPRECATED}, - {"-r, --range ", - "Retrieve only the bytes within RANGE", - CURLHELP_HTTP | CURLHELP_FTP | CURLHELP_SFTP | CURLHELP_FILE}, - {" --rate ", - "Request rate for serial transfers", - CURLHELP_CONNECTION | CURLHELP_GLOBAL}, - {" --raw", - "Do HTTP raw; no transfer decoding", - CURLHELP_HTTP}, - {"-e, --referer ", - "Referrer URL", - CURLHELP_HTTP}, - {"-J, --remote-header-name", - "Use the header-provided filename", - CURLHELP_OUTPUT}, - {"-O, --remote-name", - "Write output to file named as remote file", - CURLHELP_IMPORTANT | CURLHELP_OUTPUT}, - {" --remote-name-all", - "Use the remote filename for all URLs", - CURLHELP_OUTPUT}, - {"-R, --remote-time", - "Set remote file's time on local output", - CURLHELP_OUTPUT}, - {" --remove-on-error", - "Remove output file on errors", - CURLHELP_OUTPUT}, - {"-X, --request ", - "Specify request method to use", - CURLHELP_CONNECTION | CURLHELP_POP3 | CURLHELP_FTP | CURLHELP_IMAP | - CURLHELP_SMTP}, - {" --request-target ", - "Specify the target for this request", - CURLHELP_HTTP}, - {" --resolve <[+]host:port:addr[,addr]...>", - "Resolve host+port to address", - CURLHELP_CONNECTION | CURLHELP_DNS}, - {" --retry ", - "Retry request if transient problems occur", - CURLHELP_CURL}, - {" --retry-all-errors", - "Retry all errors (with --retry)", - CURLHELP_CURL}, - {" --retry-connrefused", - "Retry on connection refused (with --retry)", - CURLHELP_CURL}, - {" --retry-delay ", - "Wait time between retries", - CURLHELP_CURL | CURLHELP_TIMEOUT}, - {" --retry-max-time ", - "Retry only within this period", - CURLHELP_CURL | CURLHELP_TIMEOUT}, - {" --sasl-authzid ", - "Identity for SASL PLAIN authentication", - CURLHELP_AUTH}, - {" --sasl-ir", - "Initial response in SASL authentication", - CURLHELP_AUTH}, - {" --service-name ", - "SPNEGO service name", - CURLHELP_AUTH}, - {"-S, --show-error", - "Show error even when -s is used", - CURLHELP_CURL | CURLHELP_GLOBAL}, - {"-i, --show-headers", - "Show response headers in output", - CURLHELP_IMPORTANT | CURLHELP_VERBOSE | CURLHELP_OUTPUT}, - {" --sigalgs ", - "TLS signature algorithms to use", - CURLHELP_TLS}, - {"-s, --silent", - "Silent mode", - CURLHELP_IMPORTANT | CURLHELP_VERBOSE}, - {" --skip-existing", - "Skip download if local file already exists", - CURLHELP_CURL | CURLHELP_OUTPUT}, - {" --socks4 ", - "SOCKS4 proxy on given host + port", - CURLHELP_PROXY}, - {" --socks4a ", - "SOCKS4a proxy on given host + port", - CURLHELP_PROXY}, - {" --socks5 ", - "SOCKS5 proxy on given host + port", - CURLHELP_PROXY}, - {" --socks5-basic", - "Username/password auth for SOCKS5 proxies", - CURLHELP_PROXY | CURLHELP_AUTH}, - {" --socks5-gssapi", - "Enable GSS-API auth for SOCKS5 proxies", - CURLHELP_PROXY | CURLHELP_AUTH}, - {" --socks5-gssapi-nec", - "Compatibility with NEC SOCKS5 server", - CURLHELP_PROXY | CURLHELP_AUTH}, - {" --socks5-gssapi-service ", - "SOCKS5 proxy service name for GSS-API", - CURLHELP_PROXY | CURLHELP_AUTH}, - {" --socks5-hostname ", - "SOCKS5 proxy, pass hostname to proxy", - CURLHELP_PROXY}, - {"-Y, --speed-limit ", - "Stop transfers slower than this", - CURLHELP_CONNECTION}, - {"-y, --speed-time ", - "Trigger 'speed-limit' abort after this time", - CURLHELP_CONNECTION | CURLHELP_TIMEOUT}, - {" --ssl", - "Try enabling TLS", - CURLHELP_TLS | CURLHELP_IMAP | CURLHELP_POP3 | CURLHELP_SMTP | - CURLHELP_LDAP}, - {" --ssl-allow-beast", - "Allow security flaw to improve interop", - CURLHELP_TLS}, - {" --ssl-auto-client-cert", - "Use auto client certificate (Schannel)", - CURLHELP_TLS}, - {" --ssl-no-revoke", - "Disable cert revocation checks (Schannel)", - CURLHELP_TLS}, - {" --ssl-reqd", - "Require SSL/TLS", - CURLHELP_TLS | CURLHELP_IMAP | CURLHELP_POP3 | CURLHELP_SMTP | - CURLHELP_LDAP}, - {" --ssl-revoke-best-effort", - "Ignore missing cert CRL dist points", - CURLHELP_TLS}, - {" --ssl-sessions ", - "Load/save SSL session tickets from/to this file", - CURLHELP_TLS}, - {"-2, --sslv2", - "SSLv2", - CURLHELP_DEPRECATED}, - {"-3, --sslv3", - "SSLv3", - CURLHELP_DEPRECATED}, - {" --stderr ", - "Where to redirect stderr", - CURLHELP_VERBOSE | CURLHELP_GLOBAL}, - {" --styled-output", - "Enable styled output for HTTP headers", - CURLHELP_VERBOSE | CURLHELP_GLOBAL}, - {" --suppress-connect-headers", - "Suppress proxy CONNECT response headers", - CURLHELP_PROXY}, - {" --tcp-fastopen", - "Use TCP Fast Open", - CURLHELP_CONNECTION}, - {" --tcp-nodelay", - "Set TCP_NODELAY", - CURLHELP_CONNECTION}, - {"-t, --telnet-option ", - "Set telnet option", - CURLHELP_TELNET}, - {" --tftp-blksize ", - "Set TFTP BLKSIZE option", - CURLHELP_TFTP}, - {" --tftp-no-options", - "Do not send any TFTP options", - CURLHELP_TFTP}, - {"-z, --time-cond